Skip to content

Clients

You want an application to sign users in against your domain. Registering it as a client is what allows that application to send users to your domain to authenticate.

On AWS this is an app client on a Cognito user pool. The same two decisions apply here, and nothing warns you when either is answered wrongly.

Prerequisites

  • A project with an identity domain
  • The URLs your application redirects back to after sign-in

The step-by-step guide and the console walkthrough cover the operations. The rest of this page explains how it fits together.

Decision one: can it keep a secret

flowchart TB
    Q{"where does the code<br/>holding the secret run?"}
    Q -->|"in the user's browser<br/>or on their device"| PUB["public client<br/>no secret - its code can be read"]
    Q -->|"on a server you control"| CONF["confidential client<br/>issued a secret it can keep"]
    PUB --> PEX["single-page app<br/>mobile app"]
    CONF --> CEX["web application<br/>backend service"]

The test: if a user could open developer tools and read it, the client is public.

Register a client as public if you are not sure

A server-side application registered as public is weaker than it should be, and it keeps working, so the mistake goes unnoticed.

A browser application registered as confidential does not work at all, because the secret it needs cannot be kept. That failure is immediate and visible, which makes it the safer error of the two.

For a confidential client the operator generates the secret and stores it in the project as keycloak-client-<name>-secret. Read it into configuration; do not commit it.

Decision two: redirect URIs

This list is a security control, not configuration.

flowchart LR
    U["user signs in"] --> D["your domain"]
    D --> C{"is the return URL<br/>in the list?"}
    C -->|yes| APP["back to your application"]
    C -->|no| STOP["refused"]
    ATT["attacker's site"] -.->|not listed| STOP

After signing someone in, the domain returns them only to a URL matching an entry here. That is what stops an attacker redirecting a successful sign-in - and the token that comes with it - to a site of their own.

List the exact URLs your application uses. Avoid a trailing wildcard unless you genuinely need one: a pattern matching more than you intended is exactly the hole this list exists to close.

webOrigins is separate and only matters for browser applications - it is what allows the browser to make the request at all.

What is fixed

The client ID, the realm, and whether the client is public. Moving an application from public to confidential means registering a new client.

Redirect URIs and web origins can be changed, and that is the field you will come back to whenever the application moves or gains an environment.

A client can report OK and still fail

The status says the client was registered. It cannot tell whether the redirect URIs match what the application actually sends, so sign in through the application once, end to end.

  • invalid redirect uri - the URL sent is not in the list; add exactly the one the error names
  • invalid client credentials - a confidential client with the wrong secret