> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hopae.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenID Connect (OIDC)

> What OIDC is, why it matters for you, recommended client libraries, and how Hopae Connect acts as an OpenID Provider (OP).

## Overview

OpenID Connect (OIDC) is a widely adopted identity layer on top of OAuth 2.0. It standardizes how your application (the Relying Party, RP) verifies a user's identity with an OpenID Provider (OP) and receives verified identity data in a secure and interoperable way.

With Hopae Connect, your app integrates using standard OIDC discovery, authorization, token, and userinfo endpoints. That means you can use battle‑tested OIDC client libraries instead of building custom flows.

## Issuer & Endpoints

Use the issuer for the environment you are targeting.

<Tabs>
  <Tab title="Production">
    * **Issuer:** `https://connect.hopae.com`
    * **Discovery:** `GET /.well-known/openid-configuration`
    * **Auth:** `GET /auth`
    * **Token:** `POST /token`
    * **UserInfo:** `GET /userinfo`
    * **JWKS:** `GET /.well-known/jwks.json`
  </Tab>

  <Tab title="Sandbox">
    * **Issuer:** `https://sandbox.connect.hopae.com`
    * **Discovery:** `GET /.well-known/openid-configuration`
    * **Auth:** `GET /auth`
    * **Token:** `POST /token`
    * **UserInfo:** `GET /userinfo`
    * **JWKS:** `GET /.well-known/jwks.json`
  </Tab>
</Tabs>

## Why Use OIDC with Hopae Connect

* **Standards-based:** Works with any OIDC-compliant client; no custom protocol.
* **Drop-in libraries:** Use established OSS clients with built-in PKCE, token validation, discovery, and refresh logic.
* **Security best practices:** PKCE for public clients, exact `redirect_uri` matching, signed JWTs, and JWKS-based key rotation.
* **Simple configuration:** One `issuer` URL enables automatic discovery of all endpoints and capabilities.
* **Clear separation:** Verification and OIDC endpoints live on `connect.hopae.com` (or sandbox), isolated from API resource servers for security and clarity.

## How the Flow Works

<Tabs>
  <Tab title="Basic Flow">
    ```mermaid theme={null}
    sequenceDiagram
      participant User as User
      participant App as Your App
      participant Hopae as Hopae Connect
      participant eID as eID Provider

      Note over User, Hopae: Simple user verification flow

      User->>App: Clicks “Verify identity”
      App->>User: Send to Hopae Connect
      User->>Hopae: Open verification page
      Hopae->>User: Show eID options
      User->>eID: Verify identity (e.g., BankID / SmartID)
      eID-->>Hopae: Verification result
      Hopae->>User: Return to your app with a one‑time code

      App->>Hopae: Swap code for tokens (/token)
      Hopae-->>App: Access Token + ID Token
      App->>Hopae: Request user info (/userinfo)
      Hopae-->>App: Verified user profile

      App->>User: Verification complete
    ```

    * Send the user to Hopae Connect to start
    * User verifies identity with an eID and comes back with a code
    * Your app swaps the code for tokens, then requests user info
    * Create a session with the verified profile
  </Tab>

  <Tab title="Advanced (with PKCE)">
    ```mermaid theme={null}
    sequenceDiagram
      participant User as User
      participant App as Your App
      participant Hopae as Hopae Connect
      participant eID as eID Provider

      Note over User, Hopae: Authorization Code + PKCE (S256)

      App->>Hopae: GET /.well-known/openid-configuration
      Hopae-->>App: Discovery (issuer, endpoints, jwks)

      App->>App: Generate code_verifier & code_challenge
      App->>User: Redirect to Hopae /auth
      User->>Hopae: /auth?client_id=...&redirect_uri=...&response_type=code&scope=openid%20profile&state=...&code_challenge=...&code_challenge_method=S256

      Hopae->>User: Choose eID and verify identity
      User->>eID: Verify identity (QR, Mobile ID, ...)
      eID-->>Hopae: Result
      Hopae->>User: Back to app with code & state

      App->>Hopae: POST /token (code + code_verifier)
      Hopae-->>App: { access_token, id_token, token_type, expires_in }
      App->>Hopae: GET /userinfo (Bearer access_token)
      Hopae-->>App: User claims
    ```
  </Tab>
</Tabs>

<Info>
  Wondering what data you’ll get back? See the Return Data Model for normalized claims, assurance, issuers, presentation, and evidence.

  <br />

  <a href="/guides/concepts/return-data-model">Explore the Return Data Model →</a>
</Info>

## Quick Start Examples

<Tabs>
  <Tab title="Node.js (openid-client)">
    ```ts theme={null}
    import { Issuer, generators } from 'openid-client'

    const issuer = await Issuer.discover('https://sandbox.connect.hopae.com')
    const client = new issuer.Client({
      client_id: process.env.CLIENT_ID!,
      client_secret: process.env.CLIENT_SECRET, // confidential clients only
      redirect_uris: ['https://your.app/callback'],
      response_types: ['code']
    })

    const codeVerifier = generators.codeVerifier()
    const codeChallenge = generators.codeChallenge(codeVerifier)

    // 1) Redirect user to authorization URL
    const authUrl = client.authorizationUrl({
      scope: 'openid profile email',
      code_challenge: codeChallenge,
      code_challenge_method: 'S256'
    })

    // 2) After callback, exchange code for tokens
    const params = client.callbackParams(request)
    const tokenSet = await client.callback('https://your.app/callback', params, { code_verifier: codeVerifier })
    const userinfo = await client.userinfo(tokenSet.access_token!)
    ```
  </Tab>

  <Tab title="Python (Authlib)">
    ```py theme={null}
    from authlib.integrations.requests_client import OAuth2Session

    issuer = 'https://sandbox.connect.hopae.com'
    discovery = requests.get(f'{issuer}/.well-known/openid-configuration').json()

    client = OAuth2Session(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,  # confidential clients only
        scope='openid profile email'
    )

    # 1) Redirect user
    uri, state = client.create_authorization_url(discovery['authorization_endpoint'])

    # 2) Exchange code
    token = client.fetch_token(
        discovery['token_endpoint'],
        grant_type='authorization_code',
        code=auth_code,
        redirect_uri=REDIRECT_URI,
        code_verifier=CODE_VERIFIER,
    )

    # 3) UserInfo
    resp = client.get(discovery['userinfo_endpoint'])
    user = resp.json()
    ```
  </Tab>

  <Tab title="Go (go-oidc)">
    ```go theme={null}
    import (
      oidc "github.com/coreos/go-oidc"
      "golang.org/x/oauth2"
    )

    ctx := context.Background()
    provider, _ := oidc.NewProvider(ctx, "https://sandbox.connect.hopae.com")

    oauth := oauth2.Config{
      ClientID:     os.Getenv("CLIENT_ID"),
      ClientSecret: os.Getenv("CLIENT_SECRET"), // confidential only
      Endpoint:     provider.Endpoint(),
      RedirectURL:  "https://your.app/callback",
      Scopes:       []string{"openid", "profile", "email"},
    }

    // 1) Redirect to oauth.AuthCodeURL(state, ...)
    // 2) Exchange code: oauth.Exchange(ctx, code, oauth2.SetAuthURLParam("code_verifier", codeVerifier))
    // 3) Verify ID Token and call /userinfo with access token
    ```
  </Tab>

  <Tab title="Java (Spring Security)">
    ```yaml theme={null}
    spring:
      security:
        oauth2:
          client:
            registration:
              hopae:
                client-id: ${CLIENT_ID}
                client-secret: ${CLIENT_SECRET}
                scope: openid, profile, email
                redirect-uri: https://your.app/login/oauth2/code/hopae
                authorization-grant-type: authorization_code
            provider:
              hopae:
                issuer-uri: https://sandbox.connect.hopae.com
    ```
  </Tab>

  <Tab title=".NET (OpenIdConnect)">
    ```csharp theme={null}
    builder.Services.AddAuthentication(options => {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect("oidc", options => {
        options.Authority = "https://sandbox.connect.hopae.com";
        options.ClientId = Configuration["CLIENT_ID"];
        options.ClientSecret = Configuration["CLIENT_SECRET"]; // confidential only
        options.ResponseType = "code";
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("email");
    });
    ```
  </Tab>
</Tabs>

## Recommended Libraries

Choose what fits your stack. All are OIDC‑compliant and widely used:

* Node.js: [openid-client](https://github.com/panva/node-openid-client)
* Python: [Authlib](https://docs.authlib.org/)
* Java (Spring): [Spring Security OIDC](https://docs.spring.io/spring-security/reference/servlet/oauth2/login/openid.html)
* .NET: [ASP.NET Core OpenIdConnect](https://learn.microsoft.com/aspnet/core/security/authentication/openid-connect)
* Go: [go-oidc](https://github.com/coreos/go-oidc)
* PHP: [jumbojett/openid-connect-php](https://github.com/jumbojett/OpenID-Connect-PHP)

## Next Steps

<Card title="See Returned Data" icon="list" href="/guides/concepts/return-data-model">
  Learn exactly which claims and fields you receive
</Card>
