Description of the OAuth 2.0 authorization code flow
General Oauth 2.0
OAuth2 is an authentication standard used often for delegating user access to a third-party Application like web app, web api or a native app.
You can use the OAuth 2.0 authorization code grant in apps installed on a device to gain access to protected resources, such as Zehnder Cloud API.
This chapter is language-independent and describes the general authorization flow. We describe how to send and receive HTTP messages without using any open-source libraries. If possible, we recommend using the Microsoft Authentication Libraries (MSAL).
For more specific information how to use the MSAL-Library with the Cloud API look at this chapter.
The OAuth 2.0 authorization code flow is described in section 4.1 of the OAuth 2.0 specification. You can use it for authentication and authorization in most application types, including web applications, single-page applications, and natively installed applications. You can use the OAuth 2.0 authorization code flow to securely acquire access tokens and refresh tokens for your applications, which can be used to access resources that are secured by an authorization server. The refresh token allows the client to acquire new access (and refresh) tokens once the access token expires, typically after one hour.
This chapter focuses on the public clients OAuth 2.0 authorization code flow. A public client is any client application that cannot be trusted to securely maintain the integrity of a secret password. This includes single-page applications, mobile apps, desktop applications, and any application that doesn't run on a server.
Here is an example of a of the information flow:
In this Flow the "app service" is the service make use of OAuth2 to get access to the "Cloud API" (web api) in the name of the user.

Overview authorization code flow
Get an authorization code.
Authorization code is needed to get an access token.
This is the interactive part of the authentication, where user must type his/her username (mail-address) and password.Get an access token.
With the authorization code the access token can be requested by the identity provider.Use the token.
The access token is used to get access to the devices of the owner.Refresh the token.
The refresh token can be used for renewing the access token in the background without user interaction.
Important Information:
To focus on the essential information for the understanding of the authorization code flow that is needed to make use of our Cloud API, not all parameters are included in the examples below. For a full list of parameters please visit the official Azure B2C authorization code flow here
Redirect URI setup required for single-page apps
The authorization code flow uses the redirect_uri in the request, to determine the response address, where the authorization code is sent to, after successful authentication.
The following redirect URLs are configured for a Single Page Application (SPA): https://localhost:5000 or http://localhost:5000.
The former certainly provides a "warning" due to missing certificate or local certificate
For a Web APP use following redirect_uri: http://localhost
Remark:
The redirect uri is the address of your local web page you are using to provide the authentication page for the end user and include the code consuming the tokens from the authorization-code-flow. For example the MSAL-Library.
1. Get an authorization code
The authorization code flow begins with the client directing the user to the /authorize endpoint. This is the interactive part of the flow, where the user acts. In this request, the client indicates in the scope parameter the permissions that it needs to acquire from the user. The following three examples (with line breaks for readability) each use a different user flow. User flow is the policy describing the user experience of the end user by the login process. For example, which identity provider (Amazon, Google, Microsoft, ...) are allowed Multi factor authentication is mandatory or not even the password complexity that can be used for the login.
GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 &response_type=code&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_mode=query&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6%20offline_access&state=arbitrary_data_you_can_receive_in_the_response&code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl&code_challenge_method=S256
Parameter
Required?
Description
{tenant}
Required
Name of your Azure AD B2C tenant
{policy}
Required
The user flow to be run. The user flow define the authentication experience of the end user. For Cloud API: B2C_1_signin_signup_enduser.
client_id
Required
The application ID assigned for the cloud API, you can find here Application ID (Client).
response_type
Required
The response type, which must include code for the authorization code flow.
redirect_uri
Required
The redirect URI of your app, where authentication responses are sent and received by your app. It must exactly match one of the redirect URIs that you registered in the portal, except that it must be URL-encoded.
Scope
Required
A space-separated list of scopes. The openid scope indicates a permission to sign in the user and get data about the user in the form of ID tokens. The offline_access scope is optional for web applications. It indicates that your application will need a refresh token for extended access to resources.
response_mode
Recommended
The method that you use to send the resulting authorization code back to your app. It can be query, form_post, or fragment..
state
Recommended
A value included in the request that can be a string of any content that you want to use. Usually, a randomly generated unique value is used, to prevent cross-site request forgery attacks. The state also is used to encode information about the user's state in the app before the authentication request occurred. For example, the page the user was on, or the user flow that was being executed.
prompt
Optional
The type of user interaction that is required. Currently, the only valid value is login, which forces the user to enter their credentials on that request. Single sign-on will not take effect.
code_challenge
recommended / required
Used to secure authorization code grants via Proof Key for Code Exchange (PKCE). Required if code_challenge_method is included. For more information, see the PKCE RFC. This is now recommended for all application types - native apps, SPAs, and confidential clients like web apps.
code_challenge_method
recommended / required
The method used to encode the code_verifier for the code_challenge parameter. This SHOULD be S256, but the spec allows the use of plain if for some reason the client cannot support SHA256. If excluded, code_challenge is assumed to be plaintext if code_challenge is included. Microsoft identity platform supports both plain and S256. For more information, see the PKCE RFC.
At this point, the user is asked to complete the user flow's workflow. This might involve the user entering their username and password, signing in with a social identity, signing up for the directory, or any other number of steps. User actions depend on how the user flow is defined.
After the user completes the user flow, Azure AD returns a response to your app at the value you used for redirect_uri. It uses the method specified in the response_mode parameter. The response is the same for each of the user action scenarios, independent of the user flow that was executed.
A successful response that uses response_mode=query looks like this:
GET urn:ietf:wg:oauth:2.0:oob?code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq... // the authorization_code, truncated&state=arbitrary_data_you_can_receive_in_the_response // the value provided in the request
Parameter
Description
code
The authorization code that the app requested. The app can use the authorization code to request an access token for a target resource. Authorization codes are very short-lived. Typically, they expire after about 10 minutes.
state
See the full description in the table in the preceding section. If a state parameter is included in the request, the same value should appear in the response. The app should verify that the state values in the request and response are identical.
Error responses also can be sent to the redirect URI so that the app can handle them appropriately:
GET urn:ietf:wg:oauth:2.0:oob?error=access_denied&error_description=The+user+has+cancelled+entering+self-asserted+information&state=arbitrary_data_you_can_receive_in_the_response
Parameter
Description
error
An error code string that you can use to classify the types of errors that occur. You also can use the string to react to errors.
error_description
A specific error message that can help you identify the root cause of an authentication error.
state
See the full description in the preceding table. If a state parameter is included in the request, the same value should appear in the response. The app should verify that the state values in the request and response are identical.
2. Get an access token
Now that you've acquired an authorization code, you can redeem the code for a token to the intended resource by sending a POST request to the /token endpoint.
You can also request an access token for your app's own back-end Web API by convention of using the app's client ID as the requested scope (which will result in an access token with that client ID as the "audience"):
POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1Content-Type: application/x-www-form-urlencodedgrant_type=authorization_code&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...&redirect_uri=urn:ietf:wg:oauth:2.0:oob&code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong
Parameter
Required?
Description
{tenant}
Required
Name of your Azure AD B2C tenant
{policy}
Required
The user flow that was used to acquire the authorization code. You cannot use a different user flow in this request.
client_id
Required
The application ID assigned for the cloud API, you can find here Application ID (Client).
client_secret
Yes, in classic Web Apps, not used for the cloud API
The application secret that was generated for the application, this will be provided by Zehnder Group. Client secrets are used in this flow for Web App scenarios, where the client can securely store a client secret. For Native App (public client) scenarios, client secrets cannot be securely stored, and therefore are not used in this call. If you use a client secret, please change it on a periodic basis.
grant_type
Required
The type of grant. For the authorization code flow, the grant type must be authorization_code.
scope
Required
A space-separated list of scopes. A single scope value indicates to Azure AD both of the permissions that are being requested. Using the client ID as the scope indicates that your app needs an access token that can be used against your own service or web API, represented by the same client ID. The offline_access scope indicates that your app needs a refresh token for long-lived access to resources. You also can use the openid scope to request an ID token from Azure AD B2C.
code
Required
The authorization code that you acquired in the first leg of the flow.
redirect_uri
Required
The redirect URI of the application where you received the authorization code.
code_verifier
recommended
The same code_verifier that was used to obtain the authorization_code. Required if PKCE was used in the authorization code grant request. For more information, see the PKCE RFC.
A successful token response looks like this:
{"not_before": "1442340812","token_type": "Bearer","access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...","scope": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access","expires_in": "3600","refresh_token": "AAQfQmvuDy8WtUv-sd0TBwWVQs1rC-Lfxa_NDkLqpg50Cxp5Dxj0VPF1mx2Z...",}
Parameter
Description
not_before
The time at which the token is considered valid, in epoch time.
token_type
The token type value. The only type that Azure AD supports is Bearer.
access_token
The signed JWT that you requested.
scope
The scopes that the token is valid for. You also can use the scopes to cache tokens for later use.
expires_in
The length of time that the token is valid (in seconds).
refresh_token
An OAuth 2.0 refresh token. The app can use this token to acquire additional tokens after the current token expires. Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time. For more information, see the Azure AD B2C token reference.
Error responses look like this:
{"error": "access_denied","error_description": "The user revoked access to the app.",}
Parameter
Description
error
An error code string that you can use to classify types of errors that occur. You also can use the string to react to errors.
error_description
A specific error message that can help you identify the root cause of an authentication error.
3. Use the token
Now that you've successfully acquired an access token, you can use the token in requests to your back-end web APIs by including it in the Authorization header:
GET /tasks Host: mytaskwebapi.com Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...4. Refresh the token
Access tokens and ID tokens are short-lived. After they expire, you must refresh them to continue to access resources. To do this, submit another POST request to the /token endpoint. This time, provide the refresh_token instead of the code:
POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1Content-Type: application/x-www-form-urlencodedgrant_type=refresh_token&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access&refresh_token=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...&redirect_uri=urn:ietf:wg:oauth:2.0:oob
Parameter
Required?
Description
{tenant}
Required
Name of your Azure AD B2C tenant
{policy}
Required
The user flow that was used to acquire the original refresh token. You cannot use a different user flow in this request.
client_id
Required
The application ID assigned for the cloud API, you can find here Application ID (Client).
client_secret
Yes, in classic Web Apps, not used for the cloud API
The application secret that was generated for the application, this will be provided by Zehnder Group. Client secrets are used in this flow for Web App scenarios, where the client can securely store a client secret. For Native App (public client) scenarios, client secrets cannot be securely stored, and therefore are not used in this call. If you use a client secret, please change it on a periodic basis.
grant_type
Required
The type of grant. For this leg of the authorization code flow, the grant type must be refresh_token.
scope
Recommended
A space-separated list of scopes. A single scope value indicates to Azure AD both of the permissions that are being requested. Using the client ID as the scope indicates that your app needs an access token that can be used against your own service or web API, represented by the same client ID. The offline_access scope indicates that your app will need a refresh token for long-lived access to resources. You also can use the openid scope to request an ID token from Azure AD B2C.
redirect_uri
Optional
The redirect URI of the application where you received the authorization code.
refresh_token
Required
The original refresh token that you acquired in the second leg of the flow.
A successful token response looks like this:
{
"not_before": "1442340812",
"token_type": "Bearer",
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
"scope": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access",
"expires_in": "3600",
"refresh_token": "AAQfQmvuDy8WtUv-sd0TBwWVQs1rC-Lfxa_NDkLqpg50Cxp5Dxj0VPF1mx2Z...",
}Parameter
Description
not_before
The time at which the token is considered valid, in epoch time.
token_type
The token type value. The only type that Azure AD supports is Bearer.
access_token
The signed JWT that you requested.
scope
The scopes that the token is valid for. You also can use the scopes to cache tokens for later use.
expires_in
The length of time that the token is valid (in seconds).
refresh_token
An OAuth 2.0 refresh token. The app can use this token to acquire additional tokens after the current token expires. Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time. For more information, see the Azure AD B2C token reference.
Error responses look like this:
{
"error": "access_denied",
"error_description": "The user revoked access to the app.",
}Parameter
Description
error
An error code string that you can use to classify types of errors that occur. You also can use the string to react to errors.
error_description
A specific error message that can help you identify the root cause of an authentication error.