OAuth 2.0 Authorization

Streamline user authorization with the external identity providers.

Apps built with Code On Time offer inherent user and role management capabilities. For public-facing apps, the initial challenge to broader user adoption lies in convincing users to create accounts. Internet users are generally reluctant to provide their credentials on multiple websites. Enterprise apps, regardless of their complexity, must integrate seamlessly with existing security systems. IT departments are unlikely to approve apps that do not provide single sign-on for their users. Your app can address both challenges effectively due to the embedded support for OAuth 2.0 Authorization.

What Is OAuth 2.0 Authorization?

OAuth 2.0 authorization is an industry-standard protocol for authorizing third-party applications to access user data. It allows users to grant access to their data without sharing their passwords with the third-party application.

OAuth 2.0 authorization works by having the user log in to their account with the identity provider (such as Google or Facebook) and then granting permission to the third-party application to access their data. Once the user has granted permission, the third-party application can access the user's data without the user having to log in again.

OAuth 2.0 authorization is a secure and convenient way for users to authorize third-party applications to access their data. It is also a flexible protocol that can be used with a variety of identity providers and third-party applications.

Preparing App for OAuth 2.0

Your custom app requires a way to track its users. Various database tables may reference the user records to indicate who created or modified data. To tailor the user experience for different audiences, you can assign app-specific roles to the users. To achieve this, you need to install the membership support in the app database. Additionally, your app needs a location to store its runtime configuration data, which can be achieved by integrating the Content Management System.

Make sure to add both the membership system and the CMS to your application database when configuring the connection string.

You need to publish your application to a public address and enable SSL support.

The configuration of a Code On Time app for OAuth 2.0 authorization is the same uniform process for any provider. For example, let's see how to configure Google as an identity provider.

Google as Identity Provider

Let’s allow users with a valid Google account to sign in to your app.

Sign in to the production version of your app with the admin account and navigate to the Site Content. Click the floating “plus” button and proceed to register the Identity Provider by selecting the corresponding option in the list.

image6.png
Select the Identity Provider in the list to create a new identity provider option for your app users. The configuration record will be stored in the Site Content table that serves as the content management system for the app.

Press the OK button to continue. When the OAuth Identity Provider configuration form opens, choose OAuth 2.0. If you have experience setting up an API development tool for OAuth 2.0, you will likely find many familiar parameters in the form.

image4.png
This form allows registering any OAuth 2.0 identity provider to create an alternative sign-in option for the app users. Multiple generic records can be created. Other identity provider choices are the shortcuts to register the known identity providers and require fewer parameters.

Enter google in the Identifier field and press Enter. Click the Copy icon next to the Redirect Uri input field. The authorization server of the identity provider will send the authorization code to this URL. Keep the form open for now.

Client ID and Secret

It is time to create an OAuth client ID. For that, open another tab in the browser and visit the Google API Console to obtain OAuth 2.0 credentials such as a client ID and client secret that are known to both Google and your application.

The Google API Console is a platform for developers to build and manage API projects. It lets them create credentials, utilize APIs, and monitor usage. The console supports various API types, including public, private, and internal APIs. Additionally, it offers features like credential management, usage tracking, and API documentation.

Sign in to the console and access the Credentials in API & Services section. Click the Create Credentials button and choose the OAuth client ID option in the dropdown menu.

image16.png
Create the credentials of the OAuth client ID type in the Credentials section of the Google API Console.

Set the Application Type to Web Application and enter the name for your app. Add a URI in the Authorized redirect URIs section and paste the value of the Redirect Uri of your app that is already in the clipboard.

image13.png
OAuth client ID must be configured in the Credentials of the API & Services section of the Google API Console before you can configure your Code On Time application for OAuth 2.0 authorization.

Press the Create button and you will see the properties of the registered OAuth client application. You will need the Client ID and Client secret values to complete the configuration of the identity provider for your own app.

image3.png
The Client ID and the Client secret are needed to configure the OAuth 2.0 Authorization in a Code On Time app.
Do not close the form with the OAuth client parameters. The Client secret will not be available after the form is closed.

You will be able to view and change the app name and the authorized redirect URIs if necessary.

OAuth Identity Provider

Copy the Client ID to the clipboard and switch to the browser tab with the OAuth Identity Provider form. Paste the value from the clipboard into the corresponding field. Repeat the process for the Client Secret.

Complete the field in the OAuth Identity Provider form as follows:

Field

Value

Display Name

Google (OAuth 2.0 With PKCE)

Grant Type

Authorization Code (With PKCE)

Auth Uri

https://accounts.google.com/o/oauth2/v2/auth

Access Token Uri

https://www.googleapis.com/oauth2/v4/token

Revoke Uri

https://www.googleapis.com/oauth2/v4/revoke

Client Id

The Client ID of your app in the Google API Console.

Client Secret

The Client secret of your app in the Google API Console.

Code Challenge Method

SHA-256

Code Verifier

Leave the field value blank.

Scope

Leave the field value blank

Client Authentication

Send as Basic Auth header

Synchronize users

Enabled

Force users to login with this provider

Disabled

Save the form. If you reopen the identity provider record, then the OAuth Identity Provider form may look like the following.

image12.png
Your own registration of Google as identity provider will be identical with the exception of the values in the Redirect Uri, Client ID, and Client Secret fields.

Your own registration of Google as OAuth 2.0 identity provider will be virtually identical. The mandatory Display Name can be any user-friendly text. The Identifier is optional. Leave it blank if Google will be your only identity provider or enter an arbitrary unique alpha-numeric sequence if your app will use multiple OAuth 2.0 identity providers to authorize users.

The values of the Redirect Uri, Client Id, and Client Secret are unique to your own application. The former is a read-only value calculated by the app at runtime. The Redirect Uri will reflect the deployment address of your application.

We recommend setting the Grant Type to Authorization Code (With PKCE) to ensure the most secure method of user authentication. Set the Code Challenge Method to SHA-256 and leave the Code Verifier blank.

Authorization Code with PKCE Flow

The Authorization Code with PKCE (Proof Key for Code Exchange) flow is an OAuth 2.0 authorization flow that is designed to mitigate the risk of authorization code interception attacks. It works by using a randomly generated code verifier and challenge before exchanging the authorization code for an access token. This makes it more difficult for an attacker to intercept the authorization code and use it to obtain an access token.

Here is a brief overview of how the Authorization Code with PKCE flow works:

  1. The client application generates a random code verifier and calculates a code challenge from it using a cryptographic hash function.
  2. The client application redirects the user to the authorization server with the code challenge and other parameters.
  3. The user authenticates with the authorization server and grants permission to the client application to access their data.
  4. The authorization server generates an authorization code and redirects the user back to the client application.
  5. The client application exchanges the authorization code and code verifier with the authorization server for an access token.

The Authorization Code with PKCE flow is a secure and reliable way to authorize third-party applications to access user data. It is particularly useful for applications that are deployed in untrusted environments or that handle sensitive data.

Google URIs

The Auth URI points to the Google Account authorization service. Your app will redirect to the specified URL enhanced with required parameters.This will begin the authorization flow for the Google accounts. For example, the client_id parameter will identify your app, while the automatically generated code_challenge will allow the app to collect the user identity information in a secure fashion.

The Access Token URI serves as a gateway to the Google Identity API, which handles the process of obtaining and refreshing access tokens. Upon successful user authentication and authorization, the app is issued an authorization code by the authorization service. This authorization code is then utilized as a parameter within the Redirect URI previously configured in the app's Google Credentials.

The Revoke URI allows your app to notify Google that the access token is not needed anymore. This will happen when the user explicitly logs out.

Scope

By default, your app will always include the openid, email, and profile scopes in the scope parameter of the authorization URL. This instructs the authorization server to return the id_token containing the information about the user when the user grants the app access to their identity information during the sign in process.

OpenID is a decentralized authentication protocol that allows users to log in to websites and other online services using a single digital identity. Instead of creating and managing multiple usernames and passwords for different websites, users can use their OpenID to sign in to any website that supports the protocol. OpenID is designed to be secure and easy to use, and it can help to protect users from phishing attacks and other security risks.

User Authorization Flow

The standard login screen of your app will change automatically. The radio button list of identity providers is presented to the users trying to sign in. The last option in the list represents the security system of the application itself.

image5.png
The screenshot shows the login screen of the https://my.codeontime.com portal.

If there is an identity provider configured with the option to Force users to login with this provider, then the user is automatically redirected to the provider’s authorization server. Otherwise users choose their preferred method of authentication and press the Login button.

When users select Google as their authentication method, the authorization process begins. This process is controlled entirely by the identity provider vendor. If users have previously logged into other services using the same identity provider, they can skip entering their credentials and simply consent to the app accessing their identity information.

image7.png
Here is how the Google Account authorization begins if you sign in to your app when the browser is running in the incognito/private mode.

Finally, the user is redirected back to the app at the URI specified in the Redirect Url field in the identity provider configuration. Your application uses the authorization code specified in the code parameter to fetch the user identity information from Google by contacting the API specified in the Auth Token Url field of the identity provider.

The user information is received in the JSON format and includes the access_token, id_token, and optional refresh_token keys. The app will persist this information as sys/users/[USER_NAME].json “file” in the Site Content table used by the app as a general purpose CMS.

User Sign In

The id_token value specified in the user data allows your application to identify the user. Here is the sample content of the token obtained from Google.

JSON
1234567891011121314151617{
  "iss": "https://accounts.google.com",
  "azp": "4985749854-933kdd1o5ev29kapvid5hmn99nddddfoe1.apps.googleusercontent.com",
  "aud": "4985749854-933kdd1o5ev29kapvid5hmn99nddddfoe1.apps.googleusercontent.com",
  "sub": "106861556205838118498",
  "hd": "idp-domain-name.com",
  "preferred_username": "john.doe",
  "email": "john.doe@idp-domain-name.com",
  "email_verified": true,
  "at_hash": "4we-xSQFZJuXPxMupn0aYA",
  "name": "John Doe",
  "picture": "https://lh3.googleusercontent.com/a/ACg8ocIZcEYwKeUyxyNhdiexWrcjPHB-1oqUhUokL7mW2waO8meBeAxU=s96-c",
  "given_name": "John",
  "family_name": "Doe",
  "iat": 1715812203,
  "exp": 1715815803
}

Your app will use the preferred_username key to locate the user in the membership records. If a user with such a name exists, then the app will sign the user in. If the key is not present, then the app will attempt to locate the user with the name or email that matches the email key.

In the absence of an identity provider configured to synchronize users, the app will deny access if it cannot find the user in its membership records.

If the identity provider is configured to Synchronize users and the user is not found, then the new user account is created. The username of the new member is derived either from the preferred_username or from the email key. The password of the new member is a random sequence. The built-in membership system stores the hash value of the password, which makes the real password a complete mystery.

The picture key is the URL that allows your application to fetch the user picture and save it to the CMS.

Developers have access to the claims in the id_token through the BusinessRules.UserClaims property when writing “code” business rules.

Refresh Token

When a user successfully signs in to an app using Google as their identity provider, the app will obtain an access token that will remain valid for a short period. If the user closes the browser shortly after a successful sign-in and then accesses the app in a separate browser window within five minutes, they will automatically be logged in and won't need to sign in again. The login prompt will reappear after a longer period.

The identity provider may ask for "offline" access to the user's identity. This allows the app to refresh the access token without the user's involvement. If the user or the administrator of the authorization server revokes access to the user's identity, your app will automatically log the user out. If the authorization is still valid, user claims are automatically updated, the user will not be asked to sign in again until they log out explicitly.

The standard way to ask for a refresh token is to specify the offline_access scope. Google's authorization server requires the access_type parameter set to the offline value in the authorization URL to allow offline access to the user identity. Add this parameter in the Advanced Options of the Auth Url field in the identity provider configuration. If you have already tried signing in with this provider, then also include the prompt parameter with the consent value to ensure that the user’s authorization will be reissued.

text
12access_type=offline
prompt=consent

Note that there are advanced options associated with the Access Token Url. Developers can specify the parameters required by their authorization server for the initial token request and for the optional refresh request. The parameters may be specified in the request headers or in the body. The screenshot below shows the advanced parameters for Google account authorization. The parameters are presented as name/value pairs listed on separate lines. The app will encode the parameter values as needed at runtime.

image15.png
The Advanced Options dropdown allows specifying the parameters for the Auth Url and for the Access Token Url fields in the OAuth Identity Provider configuration form when the Identity Provider is set to OAuth 2.0. List parameters as name/value pairs, one per line. Values will be encoded by the application automatically.

Code On Time App as Identity Provider

In this section, we'll guide you through configuring a Code On Time application to act as an identity provider. Your application's OAuth 2.0 Identity Provider can be used with any OAuth 2.0-compliant server, such as another application built using Code On Time with its RESTful API enabled.

Apps created with Code On Time have a built-in RESTful API engine that implements a hypermedia-driven REST Level 3 API for the application data. It also implements several OAuth 2.0 Authorization flows.

Local Redirect Uri, Client Id, and Client Secret

Navigate to the Northwind application at https://demo.codeontime.com. This app was built with Code On Time and configured to expose its RESTful API to the world. Sign in with the admin credentials and navigate to the Site Content page, the content management system of the app. Click the “search” icon and find the entries containing the sys/oauth2/apps path. Select the identity consumer entry named Standalone SPA4 with RESTful Hypermedia and OAuth 2.0. This identity consumer registration record is for the app designed in the Lesson 5 of the RESTful API Workshop. We will reuse the same record to designate the Northwind application as the identity provider for our own custom app .

The Redirect Uri of the identity consumer is for the custom single-page application developed in the workshop lesson. The Local Redirect Uri of the identity consumer is a valid identity provider URI of an app created with Code On Time and running on the 60595 port at the localhost address

The identity consumer supports the Native and Server-to-Server authorization flows. The former is based on the dynamic secret and the latter relies on the static secret.

image14.png
The screenshot shows configuration parameters of the Standalone SPA4 with RESTful Hypermedia and OAuth 2.0 client application. The Redirect Uri points to the primary location of the client application. The Local Redirect Uri is the second URI recognized by the Northwind application as the legitimate client. Typically this URI will point to an app running on the development workstation.
To ensure compatibility with the Northwind's "Standalone SPA4 with RESTful Hypermedia and OAuth 2.0" registration record, create a sample application using Code On Time and make certain that the Web Server configuration specifies the 60595 port.

Another option is to modify the project settings of your existing app to use the same port.

For the sample application, we will configure the OAuth 2.0 Identity Provider utilizing the Client Id and Client Secret from the Northwind's registration record.

OAuth 2.0 Endpoints

The Northwind Demo offers OAuth 2.0 RESTful API hypermedia-enhanced endpoint accessible at https://demo.codeontime.com/oauth2/v2. Hypermedia controls (authorize, token, and revoke) enable configuration of corresponding identity provider URIs. To construct the Auth Uri, Access Token Uri, and Revoke Uri of the identity provider, add the suffixes auth, token, and revoke to the endpoint respectively.

JSON
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768{
  "_links": {
    "self": {
      "href": "/oauth2/v2"
    },
    "apps": {
      "href": "/oauth2/v2/apps"
    },
    "authorize": {
      "href": "/oauth2/v2/auth"
    },
    "token": {
      "href": "/oauth2/v2/token",
      "method": "POST"
    },
    "tokeninfo": {
      "href": "/oauth2/v2/tokeninfo"
    },
    "userinfo": {
      "href": "/oauth2/v2/userinfo",
      "method": "POST"
    },
    "revoke": {
      "href": "/oauth2/v2/revoke",
      "method": "POST"
    },
    "authorize-client-native": {
      "href": "/oauth2/v2/auth/pkce",
      "method": "POST"
    },
    "authorize-client-spa": {
      "href": "/oauth2/v2/auth/spa",
      "method": "POST"
    },
    "authorize-server": {
      "href": "/oauth2/v2/auth/server",
      "method": "POST"
    },
    "authorize-device": {
      "href": "/oauth2/v2/auth/device",
      "method": "POST"
    },
    "schema": {
      "href": "/oauth2/v2?_schema=true"
    }
  },
  "issuer": "Northwind",
  "scopes": {
    "openid": {
      "hint": "View the unique user id, client app id, API endpoint, token issue and expiration date."
    },
    "profile": {
      "hint": "View the user's last and first name, birthdate, gender, picture, and preferred language."
    },
    "address": {
      "hint": "View the user's preferred postal address."
    },
    "email": {
      "hint": "View the user's email address."
    },
    "phone": {
      "hint": "View the user's phone number."
    },
    "offline_access": {
      "hint": "Access your data anytime."
    }
  }
}

OAuth Identity Provider

Run the sample app from Code On Time, sign in with the admin account and navigate to the Site Content. Add the new Identity Provider configured as follows:

Field

Value

Identity Provider

OAuth 2.0

Display Name

Northwind Demo

Identifier

northwind

Grant Type

Authorization Code (With PKCE)

Redirect Uri

http://localhost:60595/appservices/saas/oauth2-northwind

Auth Uri

https://demo.codeontime.com/oauth2/v2/auth

Access Token Uri

https://demo.codeontime.com/oauth2/v2/token

Revoke Uri

https://demo.codeontime.com/oauth2/v2/revoke

Client Id

Copy and paste the Client Id of the identity consumer record.

Client Secret

Copy and paste the Client Secret of the identity consumer record.

Code Challenge Method

SHA-256

Code Verifier

Leave the field blank.

Scope

ofline_access

Client Authentication

Send as Basic Auth header

Synchronize users

Enabled

Force users to login with this provider

Disabled

Save the identity provider configuration. Here is how it may look in your app.

image11.png
The OAuth 2.0 Identity Provider configuration screen of an app running on the 60595 port at the localhost address. This configuration allows using the Northwind demo application as the identity provider.

Sign out of the sample application and choose the Login option.

User Authorization Flow

The standard login screen of your app will change. The radio button list with two options is presented to the user. The first option allows signing in with the Northwind Demo account. The second option in the list represents the security system of the application itself and allows users to sign in with the “local” account.

image2.png
The login screen of a Code On Time app that has one external identity provider configured with the Northwind Demo display name. The second option allows users to sign in with the local user account.

Choose the Northwind Demo in the Account and click the Login button. You will be redirected to the Northwind app. Proceed to sign in with the user account.

image10.png
The login of the Northwind application displays a hint showing the standard admin, user, and offline credentials.

When the user enters their credentials correctly, the Northwind application displays an Account Access prompt. This prompt outlines the extent of information requested by the client app, Standalone SPA4 with RESTful Hypermedia and OAuth 2.0. Note that the name may differ from your sample app because we're reusing another application's identity consumer registration record. However, if the identity provider administrator has designated the identity consumer as Trusted, the prompt won't be shown.

image9.png
The Account Access prompt is displayed when the app is not flagged as “trusted” by the administrator in the identity consumer configuration. The prompt outlines the scope of information required by the client application. The user may allow or deny access. There is an option to switch the account.

If the account access is granted, then the user is redirected to the Redirect Uri specified in the authorization request, which will sign them into the sample application.

image1.png
The homepage of the sample application is loaded when the user is signed in with the identity provider.

User Tokens

When a user signs in, their tokens are stored persistently. For instance, if a user named 'user' logs into the Northwind application using their credentials, a record called 'sys/users/user.json' will be created in the 'Site Content' section of the sample application. To view the contents of the CMS, log in to the sample application using the local 'admin' account. One of the records will contain the identity provider tokens. Additionally, there will be a record of the identity provider's registration and the user's profile picture retrieved from the identity provider.

image8.png
TBD

The contents of the user’s identity provider tokens are shown next.

JSON
12345678910{
  "access_token": "QaViPIVJ678zEw6EtpQzH~W4n6l-GK6yCJK+roxyah0Spar1fIP6TZB~DmkhyvrpXDDLzzRor07-.Ll+",
  "expires_in": 900,
  "token_type": "Bearer",
  "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2RlbW8uY29kZW9udGltZS5jb20vb2F1dGgyL3YyIiwiYXpwIjoiVEt1eXplRG1JUUtXRlZuY0pjS3BDWENXRW1jc0pQM2tCOVFwdWRlZ1RyQyIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NjA1OTUvYXBwc2VydmljZXMvc2Fhcy9vYXV0aDItbm9ydGh3aW5kIiwic3ViIjoiNzc5ZTg5MGYtOWZiYi00OThmLWFjYzQtMGNmOGU2NWIxNzllIiwiaWF0IjoxNzE2MDcwODg3LCJleHAiOjE3MTYwNzE3ODcsImVtYWlsIjoidXNlckBNeUNvbXBhbnkuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOm51bGwsImdpdmVuX25hbWUiOm51bGwsImZhbWlseV9uYW1lIjpudWxsLCJtaWRkbGVfbmFtZSI6bnVsbCwibmlja25hbWUiOm51bGwsInByZWZlcnJlZF91c2VybmFtZSI6InVzZXIiLCJwcm9maWxlIjpudWxsLCJwaWN0dXJlIjoiaHR0cHM6Ly9kZW1vLmNvZGVvbnRpbWUuY29tL29hdXRoMi92Mi91c2VyaW5mby9waWN0dXJlcy9vcmlnaW5hbC9QcndkRlIxMjd5OTJURWFlUkN2RGhMY1dUY0RjMzN3V184aVBfbEIxY3JBLmpwZWciLCJnZW5kZXIiOm51bGwsImJpcnRoZGF0ZSI6bnVsbCwiem9uZWluZm8iOiJBbWVyaWNhL0xvc19BbmdlbGVzIiwibG9jYWxlIjoiZW4tVVMiLCJ1cGRhdGVkX2F0IjpudWxsLCJzY29wZSI6Im9mZmxpbmVfYWNjZXNzIG9wZW5pZCBwcm9maWxlIGVtYWlsIn0.Xcnw4SzQNnShlvToAVkfupOflAWjXf8gC1rB3SZKNq8",
  "refresh_token": "MnyiJIKD7zUQr~ppGqKpAC2RVfdUfkrV5RS-yOgtfJUHAlBlYIXZH1xgJnAB.7.C",
  "scope": "offline_access openid profile email",
  "picture_updated": "2024-05-18T22:21:27.9640578Z",
  "expires_datetime": "2024-05-18T22:36:28.2632727Z"
}

Application uses the access_token to validate the user account and the refresh_token to refresh the access_token when it expires. The identity provider tokens are deleted when the user signs out.

User Sign In

Through the id_token content, the sample application can sign in the user. The preferred_username and email keys help identify and locate the user in the database. If no matching membership record exists, a new user account is created if the identity provider configuration specifies the Sync users option.

JSON
123456789101112131415161718192021222324{
  "iss": "https://demo.codeontime.com/oauth2/v2",
  "azp": "TKuyzeDmIQKWFVncJcKpCXCWEmcsJP3kB9QpudegTrC",
  "aud": "http://localhost:60595/appservices/saas/oauth2-northwind",
  "sub": "779e890f-9fbb-498f-acc4-0cf8e65b179e",
  "iat": 1716070887,
  "exp": 1716071787,
  "email": "user@MyCompany.com",
  "email_verified": true,
  "name": null,
  "given_name": null,
  "family_name": null,
  "middle_name": null,
  "nickname": null,
  "preferred_username": "user",
  "profile": null,
  "picture": "https://demo.codeontime.com/oauth2/v2/userinfo/pictures/original/PrwdFR127y92TEaeRCvDhLcWTcDc33wW_8iP_lB1crA.jpeg",
  "gender": null,
  "birthdate": null,
  "zoneinfo": "America/Los_Angeles",
  "locale": "en-US",
  "updated_at": null,
  "scope": "offline_access openid profile email"
}

Federated Identity Management

Code On Time allows creating the built-them-and-forget applications that help running various business processes. Integration of a large number of apps into enterprise with single sign-on is simple but may present a maintenance challenge. Managing users in the 3rd-party identity provider’s database is difficult, since the rich user metadata specific to your organization may not be easily described in a general purpose authorization server configuration.

Consider creating a custom app with Code On Time and designating it as an identity provider for your internal application. You can add custom associations of users with the organizational units and customer accounts. It is easy to enhance the id_token with this data. Custom apps can use this data for self-configuration purposes while your system administrators retain full control over the business configuration in a single repository.

You can implement a custom and flexible Federated Identity Management for your organization’s applications whether or not they are created with Code On Time. If you want to do it right, then do it yourself!

Better yet, register any number of external OAuth 2.0 compatible authorization servers in your custom identity provider (IdP) application. A single identity provider record will enable the Enterprise SSO for the entire application collection.