# Yoursafe ID Integration

Implement OAuth 2.0 / OpenID Connect with Yoursafe Identity Services.

**Example values**

All request/response snippets and parameter values in this section are example values for illustration only. Replace them with your own client credentials, endpoints, session values, and real tokens.

Systems involved

#### (Web) App

The user's browser or client app. Example Web App:{" "} `http://localhost:5173`.

#### Your backend

Your application server (OAuth client implementation). Example: `http://localhost:3000`.

#### Yoursafe

Yoursafe Identity / authorization server:{" "} `accounts.yoursafe.com`.

Arrows show the direction of the HTTP request unless noted as a redirect you issue to the browser or app.

## Step 1 User Login and Redirect

Check session state, start sign-in, load OIDC discovery, and prepare `state`/`nonce` for the redirect.

#### Session and login

Check auth state first, then start sign-in from the app.

                User action

User clicks "Sign in with Yoursafe ID".

##### Request

(Web) App → Your backend

```
GET http://localhost:3000/auth/login
```

#### Discovery

Your backend fetches OIDC metadata (server-to-server) before building the authorize redirect.

##### Request

Your backend → Yoursafe

```
GET https://accounts.yoursafe.com/.well-known/openid-configuration
```

##### Response

Yoursafe → Your backend

OpenID Provider metadata from discovery; the live document remains the source of truth. The sample below is abbreviated (`...` stands for additional keys such as logout, revocation, and introspection). Your backend reads{" "} `authorization_endpoint`,{" "} `token_endpoint`, `jwks_uri`, and related fields from this payload.

```
{
  "issuer": "https://accounts.yoursafe.com",
  "authorization_endpoint": "https://accounts.yoursafe.com/oauth2/authorize",
  "token_endpoint": "https://accounts.yoursafe.com/oauth2/token",
  "jwks_uri": "https://accounts.yoursafe.com/oauth2/jwks",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code"],
  "id_token_signing_alg_values_supported": ["RS256"],
  ...
  "scopes_supported": ["openid", "default", "profile", "platform"]
}
```

#### State and nonce

Your backend (session store only)

Generate `state` and `nonce`, then store them server-side in the session.

```
state=FfMX8LwzcisrQWH190RkCg
nonce=2RSzKHpxWleZuA3JOIcrgQ
```

#### Authorize redirect

When discovery and session values are ready, your backend finishes handling `GET /auth/login` by returning{" "} `302 Found` with `Location` set to Yoursafe authorize (below). The browser or app follows this URL in Step 2.

##### Scope

The `scope` parameter in that URL is a space-separated list (encoded as `%20` in the query string). For OpenID Connect you must include `openid` . Additional Yoursafe scopes—such as `default`,{" "} `platform`, and `profile`—tell the authorization server what kind of identity data you need; they affect consent and which **claims** can appear in tokens issued after a successful login (for example in the ID token payload).

Only request scopes your client is registered for. The live discovery document's `scopes_supported` lists what the server advertises; pairing that with the{" "} [Yoursafe ID Claims Glossary](/en/id-claims-glossary){" "} shows exactly which claims each scope unlocks, onboarding requirements (e.g. profile), and how they differ from{" "} `openid default`.

##### Response

Your backend → (Web) App

Example HTTP response from your backend:

```
HTTP/1.1 302 Found
Location: https://accounts.yoursafe.com/oauth2/authorize
  ?response_type=code
  &client_id=cljxc37g6f27s
  &redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fcallback
  &scope=openid%20default
  &state=FfMX8LwzcisrQWH190RkCg
  &nonce=2RSzKHpxWleZuA3JOIcrgQ
```

**About state and nonce**

`state` is an opaque value your backend generates and stores with the user's session before sending the user to Yoursafe. When the browser hits your callback URL, Yoursafe echoes the same `state` in the query string. Your backend must compare it to the stored value and reject the request if they differ—this mitigates cross-site request forgery and ensures the response belongs to the login you started.

`nonce` is also generated by your backend and included in the authorize request. After you exchange the code for tokens, validate the ID token and confirm its{" "} `nonce` claim matches what you stored. That ties the issued ID token to this specific authorization round and helps prevent replay of tokens minted for another request.

## Step 2 User returns via Redirect URL

After Yoursafe login, the browser or app is sent back to your registered redirect URI with a `code` or an{" "} `error`. Your backend must accept that request, validate `state`, and handle OAuth errors. For a successful authorization `code`, exchange it for tokens on the server only—never from the browser or app—then store tokens and redirect the user to your Web App.

                User action

User is redirected to Yoursafe Login by the browser.

##### Request

(Web) App → Your backend

The registered redirect URI is loaded with either a{" "} `code` or an OAuth `error` in the query string (same route; switch tabs for examples).

                        Success

                        Error

Authorization code in the query string:

```
GET http://localhost:3000/auth/callback?code=...&state=FfMX8LwzcisrQWH190RkCg
```

OAuth error in the query string:

```
GET http://localhost:3000/auth/callback?error=invalid_scope&error_description=...&state=FfMX8LwzcisrQWH190RkCg
```

#### Token exchange

Use the authorization `code` from the callback (success case above) with the same `redirect_uri` you sent to authorize.

##### Request

Your backend → Yoursafe

```
PUT https://accounts.yoursafe.com/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
code=xDE-FXbh7l1KWE...
redirect_uri=http://localhost:3000/auth/callback
client_id=cljxc37g6f27s
client_secret=***
```

##### Response

Yoursafe → Your backend

JSON token response body, typically:

```
{
  "access_token": "eyJ...abc",
  "id_token": "eyJ...xyz",
  "token_type": "Bearer",
  "expires_in": 1800,
  "scope": "openid default"
}
```

#### Redirect to Web App

After the OAuth callback handler has validated{" "} `state`, exchanged the code, and stored tokens server-side, your backend finishes that same request by returning an HTTP **response** to the browser—not a new request from the client. The browser follows the redirect and keeps the session cookie for later calls to your API.

##### Response

Your backend → (Web) App (redirect)

Use `302 Found` (or `303 See Other`) with `Location` set to your (Web) App route. On this same response, set a `Set-Cookie` header that establishes the user's session: typically an opaque session id or equivalent, with{" "} **HttpOnly** (and `Secure`,{" "} `SameSite`, and `Path` as appropriate) so JavaScript in the Web App cannot read it. The browser will send that cookie on subsequent requests to your backend.

```
HTTP/1.1 302 Found
Location: http://localhost:5173/login/success
Set-Cookie: sid=8f3c...; Path=/; HttpOnly; SameSite=Lax
```

The Web App loads at `Location`; it then calls your API for the signed-in user using that cookie (for example via `credentials: "include"`). Routine app traffic is authorized by **your**{" "} backend session, not by calling Yoursafe from the browser.

                User action

User sees a success screen and is logged in.

## Step 3 Get Authentication State

With the user on your Web App, return normalized claims from your backend and support sign-out.

#### Profile API

The Web App retrieves normalized claims from your backend (session + `id_token` decoding).

##### Request

(Web) App → Your backend

Example endpoint:

```
GET http://localhost:3000/api/me
```

##### Response

Example normalized JSON from your API:

```
{
  "authenticated": true,
  "claims": {
    "idToken": {
      "iss": "https://accounts.yoursafe.com",
      "sub": "G0Y999.yoursafe.id",
      "aud": "cljxc37g6f27s",
      "nonce": "2RSzKHpxWleZuA3JOIcrgQ",
      "aliastoken": "G0Y999.yoursafe.id",
      "accountstatus": "active",
      "countrycode": "NL"
    },
    "userInfo": {}
  }
}
```

#### Logout

End session server-side and clear cookies as appropriate.

##### Request

(Web) App → Your backend

```
POST http://localhost:3000/auth/logout
```

##### Response

Example JSON:

```
{ "ok": true }
```

## Implementation checklist

- Use exact redirect URI matching and always validate{" "} `state`.

- Validate `id_token` signature, issuer, audience, expiry, and optional `nonce`.

- Keep secrets and token exchange on the server only.

- Implement retry and timeout handling for token endpoint calls.

For exact endpoint methods, parameters, and expected response shapes, see{" "} [Yoursafe ID Endpoint Reference](/en/id-oidc-endpoints).

Next: [Claims Glossary](/en/id-claims-glossary)

Map scopes to identity and compliance claims with core checks.
