Hanzo
PlatformHanzo IAMConnecting to IAM

Standard OIDC client

Connect to Hanzo IAM with any OIDC client using discovery endpoints.

OIDC discovery

Hanzo IAM is a full OIDC implementation. If your app already uses a standard OIDC client against another IdP, you can switch to Hanzo IAM by pointing the client at Hanzo IAM’s discovery URL.

Discovery endpoints

Hanzo IAM exposes metadata at both OpenID Connect and OAuth 2.0 discovery URLs. Most clients use these to auto-configure endpoints and capabilities.

OpenID Connect discovery

<your-iam-backend-host>/.well-known/openid-configuration

#### OAuth 2.0 authorization server metadata (RFC 8414)

```url
<your-iam-backend-host>/.well-known/oauth-authorization-server

Use this if your client only needs OAuth 2.0. Both discovery URLs return the same metadata.

### Example response

Both `https://iam.hanzo.ai/.well-known/openid-configuration` and `https://iam.hanzo.ai/.well-known/oauth-authorization-server` return metadata like:

```json
{
  "issuer": "https://iam.hanzo.ai",
  "authorization_endpoint": "https://iam.hanzo.ai/oauth/authorize",
  "token_endpoint": "https://iam.hanzo.ai/oauth/token",
  "userinfo_endpoint": "https://iam.hanzo.ai/api/userinfo",
  "jwks_uri": "https://iam.hanzo.ai/.well-known/jwks",
  "introspection_endpoint": "https://iam.hanzo.ai/oauth/introspect",
  "response_types_supported": [
    "code",
    "token",
    "id_token",
    "code token",
    "code id_token",
    "token id_token",
    "code token id_token",
    "none"
  ],
  "response_modes_supported": [
    "login",
    "code",
    "link"
  ],
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "password",
    "client_credentials",
    "refresh_token",
    "urn:ietf:params:oauth:grant-type:device_code"
  ],
  "code_challenge_methods_supported": [
    "S256"
  ],
  "subject_types_supported": [
    "public"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "scopes_supported": [
    "openid",
    "email",
    "profile",
    "address",
    "phone",
    "offline_access"
  ],
  "claims_supported": [
    "iss",
    "ver",
    "sub",
    "aud",
    "iat",
    "exp",
    "id",
    "type",
    "displayName",
    "avatar",
    "permanentAvatar",
    "email",
    "phone",
    "location",
    "affiliation",
    "title",
    "homepage",
    "bio",
    "tag",
    "region",
    "language",
    "score",
    "ranking",
    "isOnline",
    "isAdmin",
    "isGlobalAdmin",
    "isForbidden",
    "signupApplication",
    "ldap"
  ],
  "request_parameter_supported": true,
  "request_object_signing_alg_values_supported": [
    "HS256",
    "HS384",
    "HS512"
  ]
}

Hanzo IAM supports all standard OAuth 2.0 grant types, including authorization code, implicit, password credentials, client credentials, and refresh token flows. The device code grant (`urn:ietf:params:oauth:grant-type:device_code`) is also available for scenarios like smart TVs or CLI tools that have limited input capabilities.

The `code_challenge_methods_supported` field indicates that Hanzo IAM supports PKCE (Proof Key for Code Exchange) with the S256 challenge method. PKCE enhances security for public clients like mobile apps and single-page applications by preventing authorization code interception attacks. When your client library supports automatic PKCE, it will use the S256 method based on this discovery metadata. For manual implementation details, see the [OAuth 2.0 documentation](/docs/how-to-connect/oauth).

### Application-Specific OIDC Endpoints

Besides the global discovery endpoint, application-specific OIDC discovery endpoints are available. Each application gets its own isolated OIDC configuration with a unique issuer. This comes in handy when running multi-tenant deployments where applications need their own certificates or when you want to gradually migrate applications without affecting others.

The application-specific discovery URLs follow these patterns:

```url
<your-iam-backend-host>/.well-known/<application-name>/openid-configuration
<your-iam-backend-host>/.well-known/<application-name>/oauth-authorization-server

For example, if you have an application named `app-example`:

```url
https://iam.hanzo.ai/.well-known/app-example/openid-configuration
https://iam.hanzo.ai/.well-known/app-example/oauth-authorization-server

The main difference is that the `issuer` and `jwks_uri` fields in the discovery response contain the application path. The `issuer` becomes `https://iam.hanzo.ai/.well-known/app-example` instead of just `https://iam.hanzo.ai`, and the `jwks_uri` points to `/.well-known/app-example/jwks`. Everything else, including the authorization and token endpoints, stays the same.

JWKS and WebFinger are also available per application:

```url
<your-iam-backend-host>/.well-known/<application-name>/jwks
<your-iam-backend-host>/.well-known/<application-name>/webfinger

The JWKS endpoint returns the public keys for verifying tokens. When an application has its own certificate configured, that certificate is used. Otherwise, it falls back to the global certificates.

Here's what the responses look like. The global endpoint returns:

```json
{
  "issuer": "https://iam.hanzo.ai",
  "jwks_uri": "https://iam.hanzo.ai/.well-known/jwks",
  "authorization_endpoint": "https://iam.hanzo.ai/oauth/authorize",
  ...
}

While the application-specific endpoint for `app-example` returns:

```json
{
  "issuer": "https://iam.hanzo.ai/.well-known/app-example",
  "jwks_uri": "https://iam.hanzo.ai/.well-known/app-example/jwks",
  "authorization_endpoint": "https://iam.hanzo.ai/oauth/authorize",
  ...
}

## List of OIDC Client Libraries

Here is a list of some OIDC client libraries for languages like Go and Java:

| OIDC client library | Language | Link                                                   |
|---------------------|----------|--------------------------------------------------------|
| go-oidc             | Go       | `https://github.com/coreos/go-oidc`                      |
| pac4j-oidc          | Java     | `https://www.pac4j.org/docs/clients/openid-connect.html` |

The table above is not exhaustive. For more OIDC client libraries, see:

1. `https://oauth.net/code/`
2. `https://openid.net/certified-open-id-developer-tools/`

## OIDC UserInfo Fields

The following table illustrates how OIDC UserInfo fields (via the `/api/userinfo` API) are mapped from properties of Hanzo IAM's User table:

| Hanzo IAM User Field | OIDC UserInfo Field |
|--------------------|---------------------|
| Id                 | sub                 |
| originBackend      | iss                 |
| Aud                | aud                 |
| Name               | preferred_username  |
| DisplayName        | name                |
| Email              | email               |
| Avatar             | picture             |
| Location           | address             |
| Phone              | phone               |

:::note

The `/api/userinfo` endpoint returns the `address` claim as a **plain string** taken from the user's `Location` field (e.g., `"New York"`), not as a structured OIDC address object. This is different from the behavior of **JWT-Standard** tokens, where `address` is returned as a proper OIDC address object built from the user's `Address` array. See [OIDC Address Claim](/docs/token/overview#oidc-address-claim) for the full explanation.

:::

UserInfo is defined [here](https://github.com/iam/iam/blob/95ab2472ce84c479be43d6fc4db6533fc738b259/object/user.go#L175-L185).

How is this guide?

Last updated on

On this page