Skip to main content
Version: v2

Add authentication

This guide shows how to add authentication to your application using the Hosted Web Authenticator integration model. Hosted Web offers an easy developer integration experience to your application as it directly handles passkey registration and authentication for you through a hosted web page.

Hosted Web is one of two Configuration Types that can be configured when creating an application. Selecting this option requires less configuration and code. Your app simply needs to redirect to Beyond Identity's Hosted Web Authenticator, and we do the rest.

The Hosted Web Authenticator can be set up using an OpenID Connect client library. Many frameworks and languages have their own. If you wish to find an OpenID Connect client, we recommend looking for one on the list of certified OpenID Connect clients.

Overview

With this guide you will:

  1. Create a Beyond Identity application using the Hosted Web configuration type.
  2. Configure an OpenID Connect client library or build your own.

Create your Beyond Identity application

Prerequisites

Depending on the region you chose when you signed up, you can access the Beyond Identity admin console for your tenant at:

tip

If you are signing in from a different computer or browser, you can enter the email address you used when you signed up. Beyond Identity will send you a one time link you can use to sign in and enroll a passkey from the new browser.

Create a new realm

So far, you have the Beyond Identity Admin Realm for your Beyond Identity tenant only. In this step, you'll create a new Realm to hold your users' identities and the configuration.

Creating a realm from the Beyond Identity Admin Console is easy.

  1. In the Admin Console, under Tenant Management, select Go to realm > Create new realm.

    Admin Console Create new realm

  2. Enter a name for your realm and click Create realm.

  3. In the confirmation dialog, switch to the new realm.

    Create new realm confirmation success

Create an application

In this step, you'll create a new Application containing the configuration for your users.

  1. From the Admin Console, under Authentication, select Apps > Add new app.

    Admin Console Apps Add new app

  2. Give your application a name.

    Admin Console Add a new application window

On the External Protocol tab, use the following values to complete this tab.

PropertyValue
Display NameDescriptive name you choose
ProtocolOIDC

Why OIDC?

OAuth2 is primarily an authorization framework for resource access, while OIDC builds on OAuth2 to provide an identity layer for authentication, allowing client applications to obtain information about the authenticated user. Both protocols are often used together in modern applications to provide a comprehensive solution for secure authentication and authorization.

Client TypeConfidential

Why Confidential?

A "confidential" client type is ideal when your application can securely store a client secret and requires enhanced security features for token exchange and accessing user-specific resources. If your application runs in an untrusted environment or you cannot securely manage a client secret, a "public" client type might be more appropriate.

PKCES256

Why S256?

Choosing the "S256" PKCE type is strongly recommended for public clients like SPAs or mobile apps. It offers a significant security improvement over the "disabled" and "plain" options, effectively protecting against code interception attacks, which are a major concern in less secure client environments. By using "S256" PKCE, you can ensure a higher level of security for your OAuth 2.0 and OIDC flows and better protect your users' data and resources.

Redirect URIsUse a route in your app that is capable of handling the authorization code exchange.

If you are using an OpenID Connect client library, a redirect URI may be specified for you.

For example: In a Next.js application using NextAuth, your redirect URI follows the pattern:

http://localhost:3000/api/auth/callback/beyondidentity

where beyondidentity in this URI is the ID of the Auth provider as configured in the providers array in NextAuth.js and /api/auth/callback/ is based on the Next.js route file structure.

Token Endpoint Auth MethodClient Secret Basic

Why Client Secret Basic?

If your OIDC client is a confidential client and you can securely store the client secret, "client_secret_basic" is the recommended option due to its security benefits and broad support across various authorization servers. However, for public clients or environments where storing the client secret securely is challenging, you might opt for alternative authentication methods like "client_secret_post" or "none," while understanding the trade-offs in security.

Grant TypeAuthorization Code

Why Authorization Code?

The "authorization_code" grant type is suitable for confidential clients, especially when your application needs to access user-specific resources, requires Single Sign-On (SSO) support, and prioritizes security in the authentication process. It provides a secure and standardized way to obtain access to user data and resources without exposing user credentials to the client application.

All other optionsUse the default values for the remaining options

On the Authenticator Config tab, use the following values to complete this tab.

PropertyValue
Configuration TypeHosted Web

Why Hosted Web?

Hosted Web handles passkey registration and authentication for you, including generating new passkeys, presenting users with authenticator choice options as needed, and validating passkey assertions. With this model, your app simply needs to redirect to Beyond Identity's hosted web authenticator, and we do the rest.

Authentication ProfileUse the recommended values for the remaining options
CHECKPOINT

Congrats! You've created and configured a Beyond Identity application. You're now ready to use the values from this applications for your OpenID Connect client.

Configure an OpenID Connect client library

Using a library is the recommended approach because it handles authorization, token exchange and accessing user info for you.

There are many libraries available depending on your application's tech stack. If you need help finding an OpenID Connect client for your tech stack, we recommend looking for one on the list of certified OpenID Connect clients.

While there are many libraries available, they all need similar values to configure. You can find all the values you need under your External Protocol section of the application you created above.

Client ID and Client Secret will be needed for all of them, but there may be some variation in the URLs needed.

note

Remeber, if your Client Type is set to Confidential in your application's External Protocol tab then you will have a Client Secret. If the Client Type is set to Public then you will not have this value.

The Issuer and the Discovery Endpoint URL are both used by the client to identify the OpenID endpoints. The Discovery Endpoint is the Issuer + /.well-known/openid-configuration.

You can also access individual endpoints in this tab. Some libraries require copying over these URLs individually rather than using an issuer/discovery endpoint. These URLs are Authorization Endpoint, Token Endpoint and User Info Endpoint.

tip

Some libraries will require you to explicitly pass scopes or explicitly define that you are using PKCE or state. Be sure to use "openid" as a scope and configure all relevant values.

For example using a NextAuth Provider:

{
id: "beyondidentity",
name: "Beyond Identity",
type: "oauth",
wellKnown: process.env.BEYOND_IDENTITY_DISCOVERY,
authorization: { params: { scope: "openid" } },
clientId: process.env.BEYOND_IDENTITY_CLIENT_ID,
clientSecret: process.env.BEYOND_IDENTITY_CLIENT_SECRET,
idToken: true,
checks: ["pkce", "state"],
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
}
},
},

Consult your library for more details on which values are needed.

Hosted Web Configuration

How it works / Configure your own client

If you are not using a library, you will need to configure your own client. Use the Authorization Endpoint, Token Endpoint, and User Info Endpoint found in your application's External Protocol tab.

Authorization

Start with the Authorization Endpoint found in your application's External Protocol tab.

This url should look like the following:

Authorization Endpoint
https://auth-$REGION.beyondidentity.com/v1/tenants/$TENANT_ID/realms/$REALM_ID/applications/$APPLICATION_ID/authorize

Copy the Authorization Endpoint from to console and append the following parameters:

/authorize
$(Authorization Endpoint)?
response_type=code
&client_id=$CLIENT_ID
&redirect_uri=$REDIRECT_URI
&scope=openid
&state=$STATE
&code_challenge_method=256
&code_challenge=$PKCE_CODE_CHALLENGE
ParameterValue
response_typecode

This parameter specifies that the authorization server should return an authorization code to the client. The code will be used by the client to request an access token.

Grant Type must be set to Authorization Code in the console application.

client_idCopy and paste the Client ID value from your application's External Protocol tab.
redirect_uriThis parameter specifies the URL to which the authorization server can send an authorization code. If a state parameter was specified in the /authorize request, then that will be echoed back to this URL as well.

This must match one of the Redirect URIs registered in your console application.

scopeopenid

Why openid?

This scope tells the authorization server to return an

The fallback content to display on prerendering
from the /token endpoint.

stateThis parameter is a random value generated by the client. It is included in the authorization request and returned in the response. This parameter helps the client maintain state between the request and the callback to prevent cross-site request forgery (CSRF) attacks.
code_challenge_method256

Why S256?

Choosing the "S256" PKCE type is strongly recommended for public clients like SPAs or mobile apps. It offers a significant security improvement over the "disabled" and "plain" options, effectively protecting against code interception attacks, which are a major concern in less secure client environments. By using "S256" PKCE, you can ensure a higher level of security for your OAuth 2.0 and OIDC flows and better protect your users' data and resources.

This value is optional. PKCE must be enabled to S256 in the console application. If it is not enabled then you should not send the code_challenge_method or code_challenge parameters.

code_challengeThis used in conjunction with code_challenge_method ensures that the authorization code obtained by the client can only be used by the client that originally requested it.

You will need to store the hash of the code_challenge so that it can be passed to the token exchange endpoint later as a code_verifier.

This value is optional. PKCE must be enabled in the console application. If it is not enabled then you should not send the code_challenge_method or code_challenge parameters.

tip

The code_challenge is generated as defined in RFC 7636, example JavaScript snippet below:

codeVerifier = crypto.randomBytes(32).toString('base64url');
codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest()
.toString('base64url');

Initiate Authorization

After you have constructed the authorization URL, ensure to URL encode it and then incorporate it into your application:

<a
href="https://auth-$REGION.beyondidentity.com/v1/tenants/$TENANT_ID/realms/$REALM_ID/applications/$APPLICATION_ID/authorize?response_type=code&amp;scope=email%20openid&amp;client_id=$CLIENT_ID&amp;state=$STATE&amp;redirect_uri=$REDIRECT_URI"
>
Login with passwordless
</a>

Hosted Web Authenticator

When a user taps the above link, they will be redirected to the Beyond Identity Hosted Web Authenticator. The user will be presented with UI that handles passkey registration and authentication. The URL that the user will land on will look like the following:

302
https://auth-$REGION.beyondidentity.com/authenticator/v1/tenants/$TENANT_ID/realms/$REALM_ID/authenticator-configs/$AUTHENTICATOR_CONFIG_ID/bi-authenticate?request=$JWT

Hosted Web OTP Email Hosted Web Passkey Hosted Web Passkey Created

Back to your application

Upon successfully completing the UI flow, the Hosted Web Authenticator will redirect the user back to your application based on the provided redirect_uri in the authorization request appended with an authorization code and a state.

302
$(REDIRECT_URI)?code=$(AUTHORIZATION_CODE)&state=$(STATE)

The code is a short-lived authorization code that the client can exchange with the authorization server for an access token. The access token is what the client application uses to access protected resources on behalf of the user.

The state should be the same random value that the client included in the initial authorization request. This helps the client maintain the integrity of the authorization process. The client should then compare the received state with the original state to ensure that the response corresponds to the correct request and that the process wasn't tampered with (to prevent CSRF attacks).

Token Exchange

Now that your client has recieved an authorization code it's time to exchange the code for an

The fallback content to display on prerendering
and
The fallback content to display on prerendering
. An access token is used to access protected resources on behalf of a user. The id token contains information about the user and can be used to prove that the user has been authenticated.

Use the Token Endpoint value from your application's External Protocol tab.

note

If the Client Type is set to Public then you will not have a Client Secret. You can still make a token exchange without the Client Secret, but it is highly recommended that you do use PKCE S256 throughout this process. POST all of the below parameters as part of the request body.

The $CLIENT_ID and $CLIENT_SECRET are sent in the Basic Authorization header.

/token
1
2
3
4
5
curl "https://auth-$(REGION).beyondidentity.com/v1/tenants/$(TENANT_ID)/realms/$(REALM_ID)/applications/$(APPLICATION_ID)/token" \
-X POST \
-u "$(CLIENT_ID):$(CLIENT_SECRET)" --basic \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=$(AUTHORIZATION_CODE)&code_verifier=$(CODE_VERIFIER)&redirect_uri=$(REDIRECT_URI)"
ParameterValue
grant_typeauthorization_code

This indicates the grant type of this token request.
codeThis is the authorization code that was obtained in the last redirect.
redirect_uriThis must match the redirect URI that was used in the initial authorization request
client_idCopy and paste the Client ID value from your application's External Protocol tab.
client_secretCopy and paste the Client Secret value from your application's External Protocol tab.

This value is optional. The Client Type must be set to Confidential in the console application.

code_verifierThe hashed value of the code_challenge sent in the original authorization request.

This value is optional. PKCE must be enabled in the console application. If it is not enabled then you should not send the code_challenge_method, code_challenge or code_verifier.

User Info

Once you have an access token you can use this to access information about the user. Use the User Info Endpoint value from your application's External Protocol tab.

GET /userinfo HTTP/1.1
Host: User Info Endpoint
Authorization: Bearer <access_token>
/token
1
2
3
curl "https://auth-$(REGION).beyondidentity.com/v1/tenants/$(TENANT_ID)/realms/$(REALM_ID)/applications/$(APPLICATION_ID)/userinfo" \
-X GET \
-H "Authorization: Bearer $(ACCESS_TOKEN)"

The following user values may be returned:

ParameterValue
subjectThe subject is used to uniquely identify the user within the context of Beyond Identity.
nameThe name of the user

This value is optional.

preferred_usernameThe preferred username is often a user-friendly string that identifies the user.

This value is optional.

emailThe email address associated with the authenticated user's account.

This value is optional.