Package: dodgeball-server-sdk
Dodgeball Server Trust SDK for PythonTable of ContentsPurposePrerequisitesRelatedInstallationUsageAPIPurposeDodgeballenables developers to decouple security logic from their application code. This has several benefits including:The ability to toggle and compare security services like fraud engines, MFA, KYC, and bot prevention.Faster responses to new attacks. When threats evolve and new vulnerabilities are identified, your application's security logic can be updated without changing a single line of code.The ability to put in placeholders for future security improvements while focussing on product development.A way to visualize all application security logic in one place.The Dodgeball Server Trust SDK for Python makes integration with the Dodgeball API easy and is maintained by the Dodgeball team.PrerequisitesYou will need to obtain a free Dodgeball account in order to leverage the Dodgeball SDK for Python.  If you don't already have an account, please sign up at:​https://app.dodgeballhq.com/signupOnce enrolled, you can obtain an API key for your application from theDodgeball developer center.RelatedCheck out theDodgeball Trust Client SDKfor how to integrate Dodgeball into your frontend applications.InstallationWe will be registering the Dodgeball SDK for .NET with nuget.  But until then, please clone the project and include it as source in your projects.Usagefromdodgeball.interfaces.api_typesimportDodgeballEventfromdodgeball.api.dodgeballimportDodgeball/**Howeveryouobtainit,pleaseregisteryourPrivateAPI*onSDKinstantiation*/private_key=this.Vars["PRIVATE_API_KEY"];dodgeball=newDodgeball(privateKey);/**ContactDodgeballforafullspecificationofthedatainput*vocabulary*/checkpoint_data={"transaction":{"amount":100,"currency":"USD"},"paymentMethod":"paymentMethodId","customer":{"primaryEmail":"simpleTest@dodgeballhq.com","dateOfBirth":"1990-01-01","primaryPhone":"17609003548","firstName":"CannedFirst"},"session":{"userAgent":"unknown user header","externalId":"UNK  RAW Session"},"mfaPhoneNumbers":SimpleEnv.get_value("MFA_PHONE_NUMBERS"),"email":"test@dodgeballhq.com"}# We just use a random session id to demonstratesession_id=str(uuid4())/**ExecuteaDodgeballCheckpointtoprotectaresource*/db_response=awaitdodgeball.Checkpoint(DodgeballEvent(type="PAYMENT",ip="128.103.69.86",data=checkpointData),null,#source tokensession_id"test@dodgeballhq.com"# user id);/**Thenfollowthecasesofis_allowed,is_denied,is_runningto*eithergiveaccesstotheresource,denyaccess,orpass*controlbacktothefrontendtovalidatetheuserusingMFA*orSharedSecrets*/if(dodgeball.is_allowed(db_response)){//Thisisthescenariounderwhichwehavecompleted//ButweshouldbeinblockedstatewithMFA//Performbackendoperationstogiveaccesstoresources}elseif(dodgeball.is_denied(db_response)){//Informtheuserthattheiraccesshasbeenrefused}elseif(dodgeball.is_running(db_response)){//PasscontrolbacktotheJSClienttorenderMFA}APIConfigurationThe package requires a secret API key as the first argument to the constructor.dodgeball=newDodgeball("secret-api-key...");Optionally, you can pass in several configuration options to the constructor:constdodgeball=newDodgeball("secret-api-key...",{// Optional configurationDodgeballConfig("https://api.dodgeballhq.com",#apiUrlTrue,#isEnabled,allowingfortestmodeoperations,apiVersion,#Only"v1"currentlysupportedlogger#Loggerifyouwishtointegrateyourownloggingsystem});OptionDefaultDescriptionapiUrlhttps://api.dodgeballhq.comThe base URL of the Dodgeball API. Useful for sending requests to different environments such ashttps://api.sandbox.dodgeballhq.com.logLevelLOGGING.ERRORRequired severity of log entries to be shownCall a CheckpointCheckpoints represent key moments of risk in an application and at the core of how Dodgeball works. A checkpoint can represent any activity deemed to be a risk. Some common examples include: login, placing an order, redeeming a coupon, posting a review, changing bank account information, making a donation, transferring funds, creating a listing.constcheckpointResponse=awaitdodgeball.checkpoint({checkpointName:"CHECKPOINT_NAME",event:{ip:"127.0.0.1",// The IP address of the device where the request originateddata:{// Arbitrary data to send in to the checkpoint...transaction:{amount:100,currency:'USD',},paymentMethod:{token:'ghi789'}}},sourceToken:"abc123...",// Obtained from the Dodgeball Client SDK, represents the device making the requestsessionId:"session_def456",// The current session ID of the requestuserId:"user_12345",// When you know the ID representing the user making the request in your database (ie after registration), pass it in here. Otherwise leave it blank.useVerificationId:"def456"// Optional, if you have a verification ID, you can pass it in here});ParameterRequiredDescriptioncheckpointNametrueThe name of the checkpoint to call.eventtrueThe event to send to the checkpoint.event.iptrueThe IP address of the device where the request originated.event.datafalseObject containing arbitrary data to send in to the checkpoint.sourceTokenfalseA Dodgeball generated token representing the device making the request. Obtained from theDodgeball Trust Client SDK.sessionIdtrueThe current session ID of the request.userIdfalseWhen you know the ID representing the user making the request in your database (ie after registration), pass it in here. Otherwise leave it blank.useVerificationIdfalseIf a previous verification was performed on this request, pass it in here. See theuseVerificationsection below for more details.Interpreting the Checkpoint ResponseCalling a checkpoint creates a verification in Dodgeball. The status and outcome of a verification determine how your application should proceed. Continue topossible checkpoint responsesfor a full explanation of the possible status and outcome combinations and how to interpret them.constcheckpointResponse={success:boolean,errors:[{code:number,message:string}],version:string,verification:{id:string,status:string,outcome:string}};PropertyDescriptionsuccessWhether the request encountered any errors was successful or failed.errorsIf thesuccessflag isfalse, this will contain an array of error objects each with acodeandmessage.versionThe version of the Dodgeball API that was used to make the request. Default isv1.verificationObject representing the verification that was performed when this checkpoint was called.verification.idThe ID of the verification that was created.verification.statusThe current status of the verification. SeeVerification Statusesfor possible values and descriptions.verification.outcomeThe outcome of the verification. SeeVerification Outcomesfor possible values and descriptions.Verification StatusesStatusDescriptionCOMPLETEThe verification was completed successfully.PENDINGThe verification is currently processing.BLOCKEDThe verification is waiting for input from the user.FAILEDThe verification encountered an error and was unable to proceed.Verification OutcomesOutcomeDescriptionAPPROVEDThe request should be allowed to proceed.DENIEDThe request should be denied.PENDINGA determination on how to proceed has not been reached yet.ERRORThe verification encountered an error and was unable to make a determination on how to proceed.Possible Checkpoint ResponsesApprovedconstcheckpointResponse={success:true,errors:[],version:"v1",verification:{id:"def456",status:"COMPLETE",outcome:"APPROVED"}};When a request is allowed to proceed, the verificationstatuswill beCOMPLETEandoutcomewill beAPPROVED.DeniedconstcheckpointResponse={success:true,errors:[],version:"v1",verification:{id:"def456",status:"COMPLETE",outcome:"DENIED"}};When a request is denied, verificationstatuswill beCOMPLETEandoutcomewill beDENIED.PendingconstcheckpointResponse={success:true,errors:[],version:"v1",verification:{id:"def456",status:"PENDING",outcome:"PENDING"}};If the verification is still processing, thestatuswill bePENDINGandoutcomewill bePENDING.BlockedconstcheckpointResponse={success:true,errors:[],version:"v1",verification:{id:"def456",status:"BLOCKED",outcome:"PENDING"}};A blocked verification requires additional input from the user before proceeding. When a request is blocked, verificationstatuswill beBLOCKEDand theoutcomewill bePENDING.UndecidedconstcheckpointResponse={success:true,errors:[],version:"v1",verification:{id:"def456",status:"COMPLETE",outcome:"PENDING"}};If the verification has finished, with no determination made on how to proceed, the verificationstatuswill beCOMPLETEand theoutcomewill bePENDING.ErrorconstcheckpointResponse={success:false,errors:[{code:503,message:"[Service Name]: Service is unavailable"}],version:"v1",verification:{id:"def456",status:"FAILED",outcome:"ERROR"}};If a verification encounters an error while processing (such as when a 3rd-party service is unavailable), thesuccessflag will be false. The verificationstatuswill beFAILEDand theoutcomewill beERROR. Theerrorsarray will contain at least one object with acodeandmessagedescribing the error(s) that occurred.Utility MethodsThere are several utility methods available to help interpret the checkpoint response. It is strongly advised to use them rather than directly interpreting the checkpoint response.dodgeball.IsAllowed(checkpointResponse)TheisAllowedmethod takes in a checkpoint response and returnstrueif the request is allowed to proceed.dodgeball.IsDenied(checkpointResponse)TheisDeniedmethod takes in a checkpoint response and returnstrueif the request is denied and should not be allowed to proceed.dodgeball.IsRunning(checkpointResponse)TheisRunningmethod takes in a checkpoint response and returnstrueif no determination has been reached on how to proceed. The verification should be returned to the frontend application to gather additional input from the user. See theuseVerificationsection for more details on use and an end-to-end example.dodgeball.IsUndecided(checkpointResponse)TheisUndecidedmethod takes in a checkpoint response and returnstrueif the verification has finished and no determination has been reached on how to proceed. Seeundecidedfor more details.dodgeball.HasError(checkpointResponse)ThehasErrormethod takes in a checkpoint response and returnstrueif it contains an error.dodgeball.IsTimeout(checkpointResponse)TheisTimeoutmethod takes in a checkpoint response and returnstrueif the verification has timed out. At which point it is up to the application to decide how to proceed.useVerificationSometimes additional input is required from the user before making a determination about how to proceed. For example, if a user should be required to perform 2FA before being allowed to proceed, the checkpoint response will contain a verification withstatusofBLOCKEDand  outcome ofPENDING. In this scenario, you will want to return the verification to your frontend application. Inside your frontend application, you can pass the returned verification directly to thedodgeball.handleVerification()method to automatically handle gathering additional input from the user. Continuing with our 2FA example, the user would be prompted to select a phone number and enter a code sent to that number. Once the additional input is received, the frontend application should simply send along the ID of the verification performed to your API. Passing that verification ID to theuseVerificationoption will allow that verification to be used for this checkpoint instead of creating a new one. This prevents duplicate verifications being performed on the user.Important Note:To prevent replay attacks, each verification ID can only be passed touseVerificationonce.Track an EventYou can track additional information about a user's journey by submitting tracking events from your server. This information will be added to the user's profile and is made available to checkpoints.awaitdodgeball.event({event:{type:"EVENT_NAME",// Can be any string you choosedata:{// Arbitrary data to track...transaction:{amount:100,currency:'USD',},paymentMethod:{token:'ghi789'}}},sourceToken:"abc123...",// Obtained from the Dodgeball Client SDK, represents the device making the requestsessionId:"session_def456",// The current session ID of the requestuserId:"user_12345",// When you know the ID representing the user making the request in your database (ie after registration), pass it in here. Otherwise leave it blank.})ParameterRequiredDescriptioneventtrueThe event to track.event.typetrueA name representing where in the journey the user is.event.datafalseObject containing arbitrary data to track.sourceTokenfalseA Dodgeball generated token representing the device making the request. Obtained from theDodgeball Trust Client SDK.sessionIdtrueThe current session ID of the request.userIdfalseWhen you know the ID representing the user making the request in your database (ie after registration), pass it in here. Otherwise leave it blank.End-to-End Example// In your frontend application...asyncplaceOrder=async(order,previousVerificationId=null)=>{constsourceToken=awaitdodgeball.getSourceToken();constendpointResponse=awaitaxios.post("/api/orders",{order},{headers:{"x-dodgeball-source-token":sourceToken,// Pass the source token to your API"x-dodgeball-verification-id":previousVerificationId// If a previous verification was performed, pass it along to your API}});dodgeball.handleVerification(endpointResponse.data.verification,{onVerified:async(verification)=>{// If an additional check was performed and the request is approved, simply pass the verification ID in to your APIawaitplaceOrder(order,verification.id);},onApproved:async()=>{// If no additional check was required, update the view to show that the order was placedsetIsOrderPlaced(true);},onDenied:async(verification)=>{// If the action was denied, update the view to show the rejectionsetIsOrderDenied(true);},onError:async(error)=>{// If there was an error performing the verification, display itsetError(error);setIsPlacingOrder(false);}});}// In your API...@POST('/api/orders')async(req,res){// In moments of risk, call a checkpoint within Dodgeball to verify the request is allowed to proceedvardbResponse=awaitdodgeball.Checkpoint(newDodgeballEvent("WITH_MFA","128.103.69.86",checkpointData),null,dateString,"test@dodgeballhq.com");Assert.IsTrue(dbResponse.success);if(dodgeball.IsAllowed(dbResponse)){// This is the scenario under which we have completed// But we should be in blocked state with MFAAssert.Fail("We should be blocked");}elseif(dodgeball.IsDenied(dbResponse)){Console.WriteLine("Pass a forbidden response to client");}elseif(dodgeball.IsRunning(dbResponse)){Console.WriteLine("Pass control back to the JS Client to render MFA");}}