## Integrate Frontegg via OAuth Authenticate users effortlessly with hosted login. Frontegg's pre-configured Login Box enables your customers to sign up and log in seamlessly to your application. Built on the OpenID Connect protocol, Frontegg’s hosted login ensures secure and reliable user authentication. Integrate hosted login into your application with just a few simple code modifications. ## Step 1: Configure hosted login In the **Frontegg portal**, navigate to the relevant [ENVIRONMENT] → Authentication → Login Method and ensure that Hosted Login is selected. Insert the redirect URLs where users will be redirected after they log in. If the requested redirect URL is not on the list, the initial request to `/authorize` will result in an error. ![oauth](/assets/native-oauth.5400d66863bd9aa1ab7785484a790e3587db29495714717b1e1269ed0fac98f8.7e3aa641.png) ## Step 2: Generating verifier and challenge code Frontegg supports the PKCE flow, which is recommended for OAuth implementations on the client side. This flow secures the token exchange using a `code_verifier` that must match the `code_challenge` generated during the initial `/authorize` request. If implementing OAuth through your backend, `code_verifier` and `code_challenge` are not required. In such cases, refer to the Authorization Code examples. Below is a snippet on how to generate the verifier and challenge code: br ```js export function createRandomString(length: number = 16): string { let text = ''; const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; } export async function generateCodeChallenge(codeVerifier: string): Promise { const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier)); // @ts-ignore return btoa(String.fromCharCode(...new Uint8Array(digest))) .replace(/=/g, '') .replace(/\+/g, '-') .replace(/\//g, '_'); } const code_verifier = createRandomString(); const code_challenge = await generateCodeChallenge(code_verifier); ``` ## Step 3: Request authentication code On your application's signup and login pages, add a button for the end user to click when logging in using hosted login. When your customers click that button, send a request to the `/authorize` ```js curl --location --request GET 'https://[your-frontegg-subdomain].frontegg.com/oauth/authorize?response_type=code&redirect_uri=[redirect_uri]&client_id=[client_id]&scope=openid+email+profile&code_challenge=[code_challenge] ``` ```js curl --location --request GET 'https://[your-frontegg-subdomain].frontegg.com/oauth/authorize?response_type=code&redirect_uri=[redirect_uri]&client_id=[client_id]&scope=openid+email+profile ``` br | Parameter | Description | Required | | --- | --- | --- | | `client_id` | Your client ID from the Administration page of the Frontegg portal | required | | `redirect_uri` | One of the redirect URLs you configured in your Frontegg portal | required | | `state` | A value that you provide here, which will be returned to you in the token exchange. `state` can be any string value you want. Use a randomly generated unique value to prevent cross-site request forgery attacks. `state` can also encode information about the user sending the authentication request, like what page they are visiting in the application. | optional | | `code_challenge` | A value that you provide so that you can use it in the token exchange with PKCE for additional security. | optional | | `app_id` | An app identifier for accounts with multiple applications. Can be copied from [ENVIRONMENT] → Applications → [App_Name] → ID | optional | | `login_hint` | An attribute that can be used for pre-filling the user's email programmatically | optional | br A successful response redirects to the `redirect_uri` with an authorization `code` and, if provided, a `state`. ```js {redirect_uri}? code={authorization_code} &state={state} ``` br You now have the authorization code that you requested. Use the authorization code to request an access token, as explained below. If you included a state parameter in the request, you should receive the same value here in the response. It is a good idea to compare the `state` here to the `state` you sent in the request to ensure the values are identical. ## Step 4: Exchange tokens The next step is to send a request to exchange tokens. With the authorization code in your possession, exchange the code for an access token for the user. When a PKCE flow is used, it is required to pass `code_verifier`. If standard authorization code flow is implemented, you should pass environment/application/API token credentials (`clientId` and `secret`) as a base64 encoded `Authorization` header. ```js curl --location --request POST 'https://[your-frontegg-subdomain].frontegg.com/oauth/token' \ --data-raw '{ "redirect_uri": "redirect_uri", "grant_type": "authorization_code", "code": "authorization_code", "code_verifier": "code_verifier" }' ``` ```js curl --location --request POST 'https://api.frontegg.com/oauth/token' \ --header 'Authorization: Basic base64(clientId:secret)' \ --data-raw '{ "redirect_uri": "redirect_uri", "grant_type": "authorization_code", "code": "authorization_code" }' ``` br For `grant_type`, the value `authorization_code` is what you should put. It is a value, not a parameter for you to fill in. For the remaining keys, for the values to insert into the body of your POST request, please refer to the following table: br | Parameter | Description | Required vs Optional | | --- | --- | --- | | `authorization_code` | The authorization code is the `authorization_code` you receive after being redirected at the end of Step 2 above | required | | `redirect_uri` | This must be the same redirect URL that you provided for the authorization request | required | | `code_verifier` | This must be the `code_verifier` that was generated along with the `code_challenge` request | required if `code_challenge` was sent in the authorization request | br If the code-to-token exchange is successful, the endpoint will return `id_token` and `access_token`: ```js { "token_type": "Bearer", "access_token": "access_token", "id_token": "id_token", "refresh_token": "refresh_token", "expires_in": xxx } ``` ## Step 5: Refresh tokens The access token that was returned in the previous step can be refreshed using the provided `refresh_token`. If standard authorization code flow is implemented, you should pass environment/application/API token credentials (`clientId` and `secret`) as a base64 encoded `Authorization` header. See an example for a refresh request below: br ```js curl --location --request POST 'https://[your-frontegg-subdomain].frontegg.com/frontegg/oauth/token' \ --header 'Content-Type: application/json' \ --data-raw '{ "grant_type":"refresh_token", "refresh_token":"refresh_token" }' ``` ```js curl --location --request POST 'https://[your-frontegg-subdomain].frontegg.com/frontegg/oauth/token' \ --header 'Authorization: Basic base64(clientId:secret)' \ --header 'Content-Type: application/json' \ --data-raw '{ "grant_type":"refresh_token", "refresh_token":"refresh_token" }' ```