Single Page Applications
  • 05 Nov 2024
  • 4 Minutes to read
  • Dark
    Light
  • PDF

Single Page Applications

  • Dark
    Light
  • PDF

Article summary

Single-page apps (or browser-based apps) run entirely in the browser after loading the Javascript and HTML source code from a web page. As the entire source is available to the browser, they cannot maintain the confidentiality of a client secret. So the secret is not used for these apps. Instead, these applications must implement the  Proof Key for Code Exchange (PKCE) extension recommended for  public clients.

The Proof Key for Code Exchange (PKCE, pronounced pixie) extension describes a technique for public clients to mitigate the threat of having the authorization code intercepted. The technique involves the client first creating a secret, and then using that secret again when exchanging the authorization code for an access token. This way if the code is intercepted, it will not be useful since the token request relies on the initial secret.

Step 1: Authorization request

Before starting the authorization process, public applications create what is known as the  code verifier. This is a cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.

Once the app has generated the code verifier it uses that to create a  code challenge. The code challenge is a BASE64-URL-encoded string of the SHA256 hash of the code verifier.

Now that the app has a code challenge, it includes that as parameter in the authorization request together with a parameter which indicates the method used to generate the challenge.

Name

Example Value

Required

Description

client_id

demoapp

yes

The Client ID set when application was registered. Identifies which app is making the request.

response_type

code

yes

Determines whether the OAuth 2.0 endpoint returns an authorization code. Always set this to the code.

scope

openid email profile offline_access visma_api:read

The “visma_api:read” scope-name above is just an example - check your API documentation for scope(s) to use.

yes

Identifies the user information that your application is requesting. One scope openid is required. The values passed in this parameter inform the consent screen that is shown to the user.

redirect_uri

https://demoapp.example.com/oauthcallback

yes

Determines where the OAuth Callback response is sent back to your application. The value of this parameter must exactly match the value added on application registration. This includes the https scheme, the same case.

code_challenge

The code challenge generated

yes

Base64-URL-encoded string of SHA256 hash of the Code Verifier.

code_challenge_method

S256 or plain

yes

Whether the challenge is the SHA256 hash of the string or the plain verifier string.

state

This field can be a Base64 encoded JSON object that can hold multiple values

no

Authorization protocols provide a state parameter. During authentication, the application sends this parameter in the authorization request, and the Authorization Server will return this parameter unchanged in the response. Your application can use this parameter in order to make sure that the response belongs to a request that was initiated by the same user. Therefore, state helps mitigate CSRF attacks. Restore the previous state of your application.  Read more

response_mode

query

no

Specifies that the response parameters are returned to client in a query string.

ui_locales

nb-NO sv-SE en-GB

no

End-User's preferred languages and scripts for the user interface, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. Values currently supported:

  • Dansk  da-DK

  • English (United Kingdom)  en-GB

  • English (US)  en-US

  • Suomi  fi-FI

  • Norsk  nb-NO

  • Nederlands  nl-NL

  • Svenska  sv-SE

  • Latviešu  lv-LV

tenant_hint

604ad704-772a-46f7-8926-571769f067e7

no

Tenant ID (context) for Applications doing authorization of user-roles as part of Visma Connect.

Examples:

GET https://connect.visma.com/connect/authorize?client_id=demoapp&response_type=code&response_mode=query&scope=openid+email+profile&redirect_uri=http://demoapp.example.com/oauthcallback&code_challenge=YOUR_CODE_CHALLENGE&code_challenge_method=S256&state=CfDJ8NbGuiMeKnBKlosjbaGWcBzxsyHJjSmlXdcP5HT0Jp_qH...tE8u1Ws&ui_locales=nb-NO+sv-SE+en-GB

Step 2: User consent

In this step, the user decides whether to grant your application the requested access or not. At this stage, Visma Connect displays a consent window with the name of your application, seeking permission to access with the user’s authorization credentials. The user can then consent or refuse to grant access to your application.

DevPortal_userConsent

Your application doesn’t need to do anything at this stage as it waits for the response from Visma Connect Authentication server indicating whether the access was granted or not.

Step 3: Authentication Response

Since the response mode for SPA applications is query, the authorization server sends the following response back to your application:

https://demoapp.example.com/oauthcallback?code=94c99b73c13c1e39f7b0a7d259628338&state=CfDJ8NbGuiMeKnBKlosjbaGWcBzxsyHJjSmlXdcP5HT0Jp_qH...tE8u1Ws

Step 4: Exchange Authorization Code for Tokens

After the app receives the authorization response, it exchanges the code for an Access Token and ID Token. The token request must include the code verifier parameter that was generated by your app before starting the authorization process. Sample request:

curl --request POST --url https://connect.visma.com/connect/token --header 'content-type: application/x-www-form-urlencoded' --data 'grant_type=authorization_code&redirect_uri=https%3A%2F%2Fdemoapp.example.com/oauthcallback%2Fcallback&code=94c99b73c13c1e39f7b0a7d259628338&client_id=demoapp&code_verifier=YOUR_CODE_VERIFIER'

Name

Example Value

Required

Description

grant_type

authorization_code

yes

As defined in the OAuth 2.0 specification, this field must contain a value of authorization_code.

redirect_uri

https://demoapp.example.com/oauthcallback

yes

The same value used on the authorization request.

code

94c99b73c13c1e39f7b0a7d259628338

yes

The authentication code returned from the initial request.

client_id

demoapp

yes

The Client ID set when application was registered. Identifies which app is making the request.

code_verifier

The generated verifier

yes

The code verifier for the PKCE request, that the app originally generated before the authorization request. This should be between 43 and 128 characters in length.

If successful, this call will return a neatly packaged token that will contain the following fields:

{ 
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjVENDc....7MTOBbdd5mgb2CHzxL0RFjs24pqC1pCeUqOjbg",
 "id_token": "eyJhbG....dsaeKOJdIHS988MLKJdsaCeUqOjbg",
 "expires_in": 3600,
 "token_type": "Bearer",
 "scope": "openid email profile" 
}

OAuth/OIDC library: Token verification and time on user device

If your OAuth/OIDC library use the local time of the device for Token-verification, then you rely on the end-users device clock to be accurate in order for the Token-verification to succeed.

SPA applications cannot have offline access support, therefore refresh tokens are never issued to these applications.

When Identity Scopes are used in the authentication request your application can retrieve additional information about the authenticated user from UserInfo Endpoint.


Was this article helpful?

Changing your password will log you out immediately. Use the new password to log back in.
First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.