Skip to main content

Sign people in with your identity provider

An internal web application behind the gateway can leave the sign-in to your identity provider. openid-connect sends a browser without a session to the provider. Once the person has signed in, it takes the browser back and keeps a session cookie from then on. This guide protects orders-api this way, with Keycloak as the provider. At the end, a person who opens the application signs in at your provider once, and your backend learns who they are from headers the gateway adds.

Before you start​

  • This guide starts from orders-api as Route requests to a backend leaves it, with no other plugin. A plugin from another guide that this page does not name can change the answers below; remove it first or work on a copy of the route.
  • openid-connect sends every request without a session to the provider's sign-in page, the requests of API clients included. On orders-api it would send mobile-app and every other API client there too, so it belongs on a route that browser users open. Follow the steps on such a route, or try them on orders-api and remove the plugin afterwards.
  • openid-connect conflicts with the plugins that sign API clients in, key-auth from Require an API key among them. With key-auth on the same route, a browser that has signed in still needs a key, and without one it is answered 401. Remove key-auth from the route first, and put it back when you return to the other guides, which start from orders-api with key-auth.
  • Someone who administers your identity provider. In step 2 you send them an address, and they send you three values back.
  • A session secret: a random text of at least 16 characters, used for nothing else. It encrypts and signs the session cookie.
  • HTTPS on the application's address. This guide turns Cookie secure on, so the browser sends the session cookie over HTTPS only. Serve HTTPS with your certificate sets it up.
  • The host name of your gateway. In the console it is the first part of the Address line on a route's Overview tab, api.example.com in this page's examples; replace it in every request below.
  • The request below calls /orders/42.
  • The Editor or Environment administrator role in this environment.

Steps​

1. Find the address people will open​

On the route's Overview tab, the Address line shows the route's addresses. Here that is https://api.example.com/orders/. People open the application under that address, and the callback address of step 2 is built from it.

2. Ask the identity provider's administrator for a client​

Send the administrator the address the provider will send browsers back to. It is the line you copied followed by a path your application does not use, https://api.example.com/orders/callback here. Ask for a client that has a secret, may sign people in through the browser, and accepts that address. Say who may use the application; this guide names no user or group, so that is set up on the provider's side.

You receive three values: the discovery address, the client ID and the client secret. The discovery address ends in /.well-known/openid-configuration, and this guide uses https://idp.example.com/.well-known/openid-configuration. For Keycloak, it is the Keycloak address followed by /realms/, the realm's name and that ending.

3. Choose openid-connect​

Open orders-api under Routes, select its Plugins tab, then Add plugin at the top right of the tab. Open the Authentication category, or type openid-connect in the search box. Select openid-connect, then Configure.

4. Connect the plugin to your provider​

Under Basics, fill in the three values. Keep Bearer only off: that is the browser sign-in, and it brings up the fields of the next step.

FieldValue
DiscoveryThe discovery address, https://idp.example.com/.well-known/openid-configuration here.
Client IDThe client ID the identity provider's administrator sent, orders-api here.
Client secretThe client secret the administrator sent. The browser sign-in needs it, and a save without it is refused.

5. Say where the provider sends people back, and how the session is kept​

FieldValue
Redirect URIhttps://api.example.com/orders/callback, the address you sent the administrator.
Scopeopenid profile email
Session › SecretYour session secret.
Session › Cookie namegateway_session
Session › Cookie HTTP onlyon
Session › Cookie secureon

Leave the other fields as they are, Logout path included. What to know shows how to give the sign-out a path this route serves.

Select Add plugin at the bottom of the panel. The plugin is saved like this, with the secrets masked:

The Add openid-connect panel with the provider's discovery address, the client and a cookie session.
openid-connect · as the console saves it
{
"discovery": "https://idp.example.com/.well-known/openid-configuration",
"client_id": "orders-api",
"client_secret": "<secret>",
"bearer_only": false,
"redirect_uri": "https://api.example.com/orders/callback",
"scope": "openid profile email",
"session": {
"secret": "<secret>",
"cookie_name": "gateway_session",
"cookie_http_only": true,
"cookie_secure": true
}
}

From now on, every browser that opens the route without a session is sent to the provider to sign in, yours included.

Check it​

Open the address from step 1 in a private browser window, with any path under it, and sign in on the provider's page. You land on the page you asked for. The request below is the same first request as a client sends it.

curl
curl -i 'https://<gateway host>/orders/42'
Without a session
A browser without a session is answered 302 to the provider's sign-in page, asking for the scope you wrote and naming the redirect_uri the provider sends it back to.
The cookie in that answer
The answer sets the gateway_session cookie, marked Secure and HttpOnly, which carries the sign-in state until the provider sends the browser back to the callback.
After signing in at the provider
Once the person has signed in at the provider, the browser comes back to the callback and the gateway sends it on to the address it first asked for. The request then goes on to your backend with the access token in X-Access-Token, the ID token's claims in X-ID-Token and the user information in X-Userinfo.
What your backend reads about the person
Decoded from Base64, X-Userinfo and X-ID-Token are JSON objects of the provider's claims about the person, such as preferred_username; X-ID-Token also names the provider in iss.

What to know​

  • The callback path has to be one this route serves. The provider sends the browser there with the sign-in code, and only this route finishes the sign-in. The same address is registered at the provider.
  • The people it signs in are not consumers. No consumer or credential is created for them, the backend receives no X-Consumer-Username, and a plugin that lets only named consumers through answers 401 because it finds none. Your backend tells people apart by X-Userinfo.
  • To sign people out, set Logout path to a path this route serves, /orders/logout here. The default, /logout, is not under /orders/*. A request to the path is answered with a redirect to the provider's sign-out page.
  • For API clients that hold a token from the provider, turn Bearer only on instead. Every request then has to carry a bearer token in its Authorization header, and a token that lacks a scope under Required scopes is answered 403.
G8 dev