Skip to main content

Server flow

Server flow

Make sure you set up your app in the API Console to enable it to use these protocols and authenticate your users. When a user tries to log in with RP OAuth 2.0 interface, you need to:

  • Create an anti-forgery state token
  • Send an authentication request to RP
  • Confirm the anti-forgery state token
  • Exchange code for access token and ID token
  • Obtain user information from the ID token
  • Authenticate the user

Create an anti-forgery state token

You must protect the security of your users by preventing request forgery attacks. The first step is creating a unique session token that holds state between your app and the user's client. You later match this unique session token with the authentication response returned by the RP OAuth Login service to verify that the user is making the request and not a malicious attacker. These tokens are often referred to as cross-site request forgery (CSRF) tokens.

One good choice for a state token is a string of 30 or so characters constructed using a high-quality random-number generator. Another is a hash generated by signing some of your session state variables with a key that is kept secret on your back-end.

Send an authentication request to RP

The next step is forming an HTTPS GET request with the appropriate URI parameters. Note the use of HTTPS rather than HTTP in all the steps of this process; HTTP connections are refused. You should retrieve the base URI from the Discovery document using the authorization_endpoint metadata value. The following discussion assumes the base URI is https://oauth2-cl.dizme.io/v2.0/oauth2/auth For a basic request, specify the following parameters:

  • client_id, which you obtain from the API Console
  • response_type, which in a basic authorization code flow request should be code in case of Javascript auth use id_token
  • scope, which in a basic request should be openid
  • redirect_uri should be the HTTP endpoint on your server that will receive the response from RP. The value must exactly match one of the authorized redirect URIs for the OAuth 2.0 client, which you configured in the API Console Credentials page. If this value doesn't match an authorized URI, the request will fail with a redirect_uri_mismatch error
  • state should include the value of the anti-forgery unique session token, as well as any other information needed to recover the context when the user returns to your application, e.g., the starting URL.
  • nonce is a random value generated by your app that enables replay protection when present.
  • hl should be set if there is a need to force language (by default is supported en, it see also Localization on how to customize page) otherwise language will be selected based on browser settings.

Here is an example of a complete OpenID Connect authentication URI, with line breaks and spaces for readability:

https://oauth2-cl.dizme.io/v2.0/oauth2/auth?
response_type=code&
client_id=2a9ead06-f829-43ea-9e8e-39bc62be3b00&
scope=openid&
redirect_uri=https://example.com/oauth_back_dizme/&
state=5RP7TK9lgvZPSti&
nonce=8rYBFeJpYMVx6DY&
hl=it

Confirm anti-forgery state token

The response is sent to the redirect_uri that you specified in the request. All responses are returned in the query string, as shown below:

https://example.com/code?state=5RP7TK9lgvZPSti&code=3a9eaddd-f829-43ea-9e8e-39bc62be3bbb&scope=openid

On the server, you must confirm that the state received from RP matches the session token you created in Step 1. This round-trip verification helps to ensure that the user, not a malicious script, is making the request.

Exchange code for access token and ID token

The response includes a code parameter, a one-time authorization code that your server can exchange for an access token and ID token. Your server makes this exchange by sending an HTTPS POST request. The POST request is sent to the token endpoint, which you should retrieve from the Discovery document using the token_endpoint metadata value. The following discussion assumes the endpoint is https://oauth2-cl.dizme.io/v2.0/oauth2/token. The request must include the following parameters in the POST body:

  • code - The authorization code that is returned from the initial request.
  • client_id - The client ID that you obtain from the API Console Credentials page, as described in Obtain OAuth 2.0 credentials.
  • client_secret - The client secret that you obtain from the API Console Credentials page, as described in Obtain OAuth 2.0 credentials.
  • redirect_uri - An authorized redirect URI for the given client_id specified in the API Console Credentials page, as described in Set a redirect URI.
  • grant_type - This field must contain a value of authorization_code, as defined in the OAuth 2.0 specification

The actual request might look like the following example (in case of client_secret_post:

POST /v2.0/oauth2/token HTTP/1.1
Host: https://oauth2-cl.dizme.io
Content-Type: application/x-www-form-urlencoded

code=somecode&
client_id=your-client-id&
client_secret=your-client-secret&
redirect_uri=https%3A//example.com/code&
grant_type=authorization_code

or using Basic Auth according to client_secret_basic flow

POST /v2.0/oauth2/token HTTP/1.1
Host: https://oauth2-cl.dizme.io
Authorization: Basic eW91ci1jbGllbnQtaWQ6eW91ci1jbGllbnQtc2VjcmV0
Content-Type: application/x-www-form-urlencoded

code=somecode&
redirect_uri=https%3A//example.com/code&
grant_type=authorization_code

Obtain user information from the ID token

An ID Token is a JWT (JSON Web Token), that is, a cryptographically signed Base64-encoded JSON object. Normally, it is critical that you validate an ID token before you use it, but since you are communicating directly with RP over an intermediary-free HTTPS channel and using your client secret to authenticate yourself to RP, you can be confident that the token you receive really comes from RP and is valid. If your server passes the ID token to other components of your app, it is extremely important that the other components validate the token before using it.

An ID token is a JSON object containing a set of name/value pairs. Here's an example, formatted for readability:

{
  "email": "test@etuitus.it",
  "email_verified": true,
  "exp": 1622111273,
  "iat": 1622110673,
  "iss": "https://oauth2-cl.dizme.io",
  "jti": "FqdY0kldHrHU-tqqGjw9zQ",
  "nbf": 1622110673,
  "nickname": "Dizme:sergio",
  "nonce": "281e6f72e2e2a6da53fd90fa16aeb6321f87de88a2cd0ff4dadef663dbb4c39b"
}

Authenticate the user

After obtaining user information from the ID token, you should query your app's user database. If the user already exists in your database, you should start an application session for that user if all login requirements are met by the RP API response.

If the user does not exist in your user database, you should redirect the user to your new-user sign-up flow. You may be able to auto-register the user based on the information you receive from RP, or at the very least you may be able to pre-populate many of the fields that you require on your registration form. In addition to the information in the ID token, you can get additional user profile information at our user profile endpoints.

Scopes

Scope Required Claims
openid yes nickname
email no email, email_verified
phone no phone_number, phone_number_verified

Scopes can be combined and must start with openid one. When in Authenticating step, only scope created for particular client_id can be used.