OpenPass API authorization code flow

TIP: The Trade Desk recommends using an SDK because it is the easiest option. It can do a lot of the work for you, such as managing security features and returning the user's ID token and access token. If you want to manually implement code for various functions using our API endpoints, use this guide.

This page includes information to help you get up and running with the OpenPass API using the redirect flow for web apps.

NOTE: For apps built for smart TVs and similar devices, use the device grant flow so that the user can enter the authentication code on a separate device.

Setup and requirements

Before implementing the authentication flow, be sure to register the client application with OpenPass. See the following for more information.

API version

The current version of the OpenPass API is v1.

Open API spec

Download the OpenAPI specification using the following endpoint: GET /.well-known/jwks.

OpenPass open ID connect URLs

The following table lists the OpenPass OIDC URLs.

Endpoints URL
GET /v1/api/authorize https://auth.myopenpass.com/v1/api/authorize
POST /v1/api/token http://auth.myopenpass.com/v1/api/token

Implement the OpenPass API

IMPORTANT: Be sure to provide a list of redirect URIs when setting up your account. This is required for the flow to work properly.

If you choose to implement OpenPass using the API instead of an SDK, you'll need to implement code to complete the various functions using the OpenPass API endpoints.

The following are high-level steps for implementing OpenPass using the API:

  1. Prepare security parameters
  2. Generate and navigate to the authorize URL
  3. Exchange authorization code for tokens

Prepare security parameters

As part of the user authentication process, OpenPass supports PKCE as an optional security feature. If PKCE is enabled, OpenPass supports the additional parameters in the following table.

PKCE Parameter Description Sample Value
code_verifier A high-entropy cryptographic random string with a minimum length of 43 characters.
For details, see POST /v1/api/token.
762ac555-cabc-452b-972d-4aaaba9cfb2f
code_challenge A Base64 URL-encoded SHA256 hash of the code_verifier value or, if the client is unable to support this, just the code_verifier value, unmodified.
For details, see GET /v1/api/authorize.
1c1d219f-1610-4174-8d24-d75c5cce875a
code_challenge_method Either the S256 value if the code_challenge was created by SHA256 hashing of the code_verifier; or plain if using the code_verifier value unmodified.
For details, see GET /v1/api/authorize.
S256

The code challenge is sent in the GET /v1/api/authorize request, and OpenPass stores this value. Later on, the code verifier is sent to the POST /v1/api/token endpoint along with the authorization code in the code property. OpenPass validates the code verifier against the code_challenge value that it previously stored.

This sequence makes sure that the original GET /v1/api/authorize request was sent by the same actor as the POST /v1/api/token request, and prevents cross-site request forgery (CSRF) and authorization code injection attacks.

You can generate the PKCE parameters by using the following pseudo-code as a guideline:

    code_verifier = randomString(length=43)
    code_challenge = base64UrlEncode(sha256(toAscii(code_verifier)))
    code_challenge_method = "S256"

Generate and navigate to the authorize URL

If you're using the redirect flow, the client initiates the authentication flow by directing the user to the authorize URL on a browser with a full-page redirect. A common approach is to generate the authorize URL and link an OpenPass-branded Sign In with OpenPass button to it.

You must generate and store the state parameter, and the optional PKCE security parameters if PKCE is enabled, because they are required later when exchanging the authorization code for the OpenPass tokens. There are multiple ways of doing this. Two examples are:

The authorize base URL is https://auth.myopenpass.com/v1/api/authorize

The following table summarizes the query string parameters. For details, see GET v1/api/authorize.

Parameter Additional Information
client_id The unique ID provided to you by The Trade Desk for your client. If you don't have a client_id value, ask your contact at The Trade Desk.
redirect_uri The URI that OpenPass redirects back to after user sign-in or an error during the sign-in. This URI must match the one set up in your client configuration with no fragments. See Account setup in the Getting Started guide.
response_type A parameter required by OpenID Connect. For OpenPass, the value must be code.
scope A parameter required by OpenID Connect. For OpenPass, the value must be openid.
state Another security parameter to help prevent forgery attacks. Often, the state parameter is a random string with sufficient length and entropy.
code_challenge See Prepare security parameters.
code_challenge_method See Prepare security parameters.

Example code

The following example is pseudo-code to demonstrate an implementation approach for generating and navigating to the URL. This example includes the Java pseudo-code, corresponding HTML coding, and implements it in the backend.

String generateAuthorizeUrl(String userSessionId) {

    var clientId = "123abc";
    var redirectUri = urlEncode("https://yoursite.com/handle_op_callback");

    var state = generateRandomString(50);
    var codeVerifier = generateRandomString(50);
    var codeChallenge = base64UrlEncode(sha256Hash(codeVerifier);
    var codeChallengeMethod = "S256";
    
    this.securityParameterStorage.store(userSessionId, codeVerifier, state);

    var authorizeUrlTemplate = "https://auth.myopenpass.com/v1/api/authorize?response_type=code&scope=openid&client_id=%s&redirect_uri=%s&state=%s&code_challenge_method=%s&code_challenge=%s";

    return String.format(authorizeUrlTemplate, clientId, redirectUri, state, codeChallengeMethod, codeChallenge);
}

The following HTML implements the example in the user interface, providing the Sign In with OpenPass button to the user and triggering the underlying code when the user clicks Sign In to OpenPass.

<a href="{{authorizeUrl}}">Sign In to OpenPass</a>

Example call to the authorize endpoint

The following example shows a call to the authorize endpoint with all required parameters and values.

https://auth.myopenpass.com/v1/api/authorize?response_type=code&client_id=29352915982374239857&scope=openid&state=97166977ea60581eee4a701a4287f656&code_challenge_method=S256&code_challenge=f_I4cgCYHdurO9gHjtAtkOb3fzybXNX-_B2VW2M8iNs&redirect_uri=https%3A%2F%2Fsite.opw1.net%2Fredirect-callback

Exchange authorization code for tokens

In the redirect flow, after the user has navigated to the authorize URL, several things can happen:

Successful sign-in

The following is the sequence of steps for a successful sign-in. When you have a successful result, follow the additional steps to verify the ID token.

  1. OpenPass redirects the page to the redirect_uri that was set on the authorize URL. The request includes two parameters on the query string:
    • code: A requirement for the next step to complete the authentication flow and receive authentication tokens.
    • state: A security parameter to help prevent forgery attacks. See state parameter.
  2. The client must handle the redirect (GET) request to the redirect_uri and complete the authentication process: a. Verify that the state value you passed to the authorize endpoint matches the one sent in this redirect request. b. If the state value does not match, abort the authentication process and display an error to the user or ask them to sign in again.
  3. The client exchanges the authorization code value for the authentication tokens. When the tokens are verified, the user is authenticated. To do this, the client sends a POST HTTP request to https://auth.myopenpass.com/v1/api/token with a Basic Authorization header (server-side integrations only) and the following parameters (content-type: application/x-www-form-urlencoded):
    • client_id (only if the Basic Authorization header is not included): Your Client ID from OpenPass. Must be the same client_id that you passed to the authorize URL.

    NOTE: The Basic Authorization header is required only when supplying a client secret (server-side integration). For client-side integrations where this header is not included, the client_id parameter is required instead. These options are mutually exclusive.

    • redirect_uri: The same redirect_uri that you passed to the authorize URL.
    • code: The authorization code that you retrieved from the redirect query string.
    • grant_type: Must be the authorization_code.
    • code_verifier: The code_verifier that was generated when constructing the code_challenge for the authorize URL.

NOTE: This request can be issued from the client/browser or on the server side.

The result you get is either a success (200) or an error (400-500) with a JSON body as follows:

The ID token is a JWT that contains information about the authenticated user including the user email address. The access token is also a JWT, but it is used to access protected resources.

To verify the ID token JWT, follow these steps (or use a library such as Verify a JWT from Auth0):

  1. Get the OpenPass JWKS from https://auth.myopenpass.com/.well-known/jwks.
  2. Get the Key ID from the ID token JWT headers.
  3. Get the correct JWK from the JWKS using the Key ID. This is the public signing key for the JWT.
  4. Verify the JWT signature using the JWK.
  5. Verify that the algorithm used to generate the JWT is the same algorithm listed in the JWK.
  6. Verify that the JWT token issuer is https://auth.myopenpass.com.

Example code for sign-in

The following example is pseudo-code to demonstrate an implementation approach for managing the sign-in process.

void handleOpenPassAuthorizeRedirect(HttpRequest request, String userSessionId) {

    var clientId = "123abc";
    var redirectUri = urlEncode("https://yoursite.com/handle_op_callback");

    var state = getParameter(request.query, "state");
    var authCode = getParameter(request.query, "code");

    var originalSecurityParameters = this.securityParameterStorage.get(userSessionId);

    // Make sure that the state originally generated and passed in the authorize URL
    // matches the state on the redirect request.
    verifyStateMatch(originalSecurityParameters.state, state);

    // The code_verifier is passed to the token endpoint, and is then matched against the code_challenge
    // that was passed in to the authorize URL.
    var postBodyParameters = new HashMap<String, String>();
    parameters["clientId"] = clientId;
    parameters["redirect_uri"] = redirectUri;
    parameters["code"] = authCode;
    parameters["grant_type"] = "authorization_code";
    parameters["code_verifier"] = securityParameters.codeVerifier;

    var response = http.post("https://auth.myopenpass.com/v1/api/token", postBodyParameters);
    var rawIdTokenJwt = response.json()["id_token"];

    // When the JWT is verified, we can say that the user is authenticated.
    DecodedJWT idToken = verifyIdToken(rawIdTokenJwt);

    System.out.println("User email: " + idToken.sub);
}

void verifyIdToken(String rawIdTokenJwt){

    // decode JWT to check for valid structure.
    DecodedJWT decodedJwt = JWT.decode(rawIdTokenJwt);

    // Connect to the OpenPass JWKS provider endpoint to retrieve the JSON web key related to the JWT key id.
    JwkProvider jwkProvider = new UrlJwkProvider("https://auth.myopenpass.com/.well-known/jwks");
    Jwk jwk = jwkProvider.get(decodedJwt.getKeyId());

    // Get the public key from the JWK endpoint and create verification algorithm.
    PublicKey publicKey = jwk.getPublicKey();
    Algorithm algorithm = Algorithm.RSA256((RSAKey) publicKey);

    // verify that the JWT has the expected algorithm and is signed and issued by OpenPass.
    JWTVerifier verifier = JWT.require(algorithm).withIssuer("https://auth.myopenpass.com").build();

    verifier.verify(decodedJwt);

    return decodedJwt;
}

Unsuccessful sign-in

If the sign-in was unsuccessful, you must handle the error redirect. OpenPass redirects to the redirect URI you provided in the redirect_uri parameter on the Authorize URL and includes error details on the query string of that request.

Example unsuccessful response

https://example.com/handle_op_redirect?error=invalid_client&error_description=Client+Does+Not+Exist

Additional resources

For more information, see the following pages: