--- title: "OAuth 2.0 Flow" slug: "oautch-2-0-flow" updated: 2026-06-24T07:08:26Z published: 2026-06-24T07:08:26Z canonical: "help.frisbii.com/oautch-2-0-flow" --- > ## Documentation Index > Fetch the complete documentation index at: https://help.frisbii.com/llms.txt > Use this file to discover all available pages before exploring further. # OAuth 2.0 Flow Frisbii Media supports OAuth 2.0 for user authentication. This is the recommended approach when using Frisbii Media as your SSO provider, as it provides refresh tokens for long-lived sessions and built-in CSRF protection. --- ## How the flow works ![](https://cdn.document360.io/b84e1b5d-2ba6-4465-8c62-fb45a2f31314/Images/Documentation/oauth2_authorization_flow.svg) 1. The user is redirected to the Frisbii Media login screen 2. After login, the user is redirected back to your server with an **access code** 3. Your server exchanges the access code for an **access token** and a **refresh token** 4. You use the access token to fetch the user's profile from the Frisbii Media API --- ## Step 1 – Start the login (CSRF token + redirect) Before redirecting the user, generate a CSRF state token and store it in the server-side session: **PHP:** ```php $state = md5(rand()); $_SESSION['oauth_state'] = $state; ``` **Java:** ```java String state = new BigInteger(130, new SecureRandom()).toString(32); request.session().attribute("state", state); ``` **Python:** ```python state = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(32)) session['state'] = state ``` Then trigger the Frisbii Media login using the JavaScript SDK: ```javascript var config = {    ssoRedirectURL: 'https://example.com/oauth/callback', // must be registered in Frisbii Media backend    scope: 'profile' }; plenigo.login(config); ``` The `ssoRedirectURL` must be registered in the Frisbii Media merchant backend. If it is not registered (or at least the URL prefix is not registered), the login will return an error. --- ## Step 2 – Receive the access code After the user logs in, Frisbii Media redirects to your `ssoRedirectURL` with these query parameters: ```plaintext https://example.com/oauth/callback?state=YOUR_STATE&code=AdE123412EdVD ``` | Parameter | Description | | --- | --- | | `state` | The CSRF token you passed during the login request | | `code` | The authorization code to exchange for an access token | **Validate the CSRF token first:** ```php if ($_GET['state'] !== $_SESSION['oauth_state']) {    // Potential CSRF attack — abort with HTTP 401 } ``` --- ## Step 3 – Exchange the code for an access token Make a server-side `POST` request to: ```plaintext POST https://api.frisbii-media.com/api/v2/oauth2/verify ``` **Request body parameters:** | Parameter | Value | Required | | --- | --- | --- | | `grant_type` | Must be `authorization_code` | ✅ | | `code` | The authorization code from the redirect | ✅ | | `redirect_uri` | The same `ssoRedirectURL` used during login | ✅ | | `client_id` | Your Frisbii Media Company ID | ✅ | | `client_secret` | Your Frisbii Media company secret | ✅ | | `state` | Optional identifier, returned as-is in the response | | **Successful response:** | Field | Description | | --- | --- | | `access_token` | Token to use for API requests on behalf of this user | | `token_type` | Always `bearer` | | `expires_in` | Lifetime of the access token in seconds | | `refresh_token` | Token to use when the access token expires | | `state` | Echoed back if you sent it in the request | Store both the `access_token` and `refresh_token` in the user's server-side session. --- ## Step 4 – Fetch the user profile Use the `access_token` to retrieve the user's Frisbii Media profile: ```plaintext GET https://api.frisbii-media.com/api/v2/profile Authorization: Bearer {access_token} ``` Compare the returned `customerId` with your user database: - **Not found** → create a new user record with the Frisbii Media profile data - **Found** → log the user in; optionally update changed profile fields --- ## Refresh the access token Access tokens have a limited lifetime. When a token expires, use the `refresh_token` to obtain a new one without re-prompting the user. ```plaintext POST https://api.frisbii-media.com/api/v2/oauth2/renew ``` **Request body parameters:** | Parameter | Value | Required | | --- | --- | --- | | `grant_type` | Must be `refresh_token` | ✅ | | `refresh_token` | The refresh token from the initial token exchange | ✅ | | `client_id` | Your Frisbii Media Company ID | ✅ | | `client_secret` | Your Frisbii Media company secret | ✅ | | `state` | Optional identifier | | **Successful response:** | Field | Description | | --- | --- | | `access_token` | New access token | | `token_type` | Always `bearer` | | `expires_in` | Lifetime of the new access token | > [!NOTE] > If the refresh token is no longer valid (e.g. the user logged out everywhere), you must restart the full login flow from Step 1. > > Requesting a new access token invalidates all previous refresh tokens. Always save the new refresh token from each renewal response. --- ## Error responses Both `/verify` and `/renew` return error responses in this format: ```json {    "error": "invalid_grant",    "error_description": "The authorization code is invalid or has expired" } ``` Possible error codes follow the [OAuth 2.0 specification](https://tools.ietf.org/html/draft-ietf-oauth-v2-31). ---