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-apias 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-apiit would sendmobile-appand 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 onorders-apiand 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-apiwith 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.comin 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.
| Field | Value |
|---|---|
| Discovery | The discovery address, https://idp.example.com/.well-known/openid-configuration here. |
| Client ID | The client ID the identity provider's administrator sent, orders-api here. |
| Client secret | The 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
| Field | Value |
|---|---|
| Redirect URI | https://api.example.com/orders/callback, the address you sent the administrator. |
| Scope | openid profile email |
| Session › Secret | Your session secret. |
| Session › Cookie name | gateway_session |
| Session › Cookie HTTP only | on |
| Session › Cookie secure | on |
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:
{
"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 -i 'https://<gateway host>/orders/42'
- Without a session
- A browser without a session is answered
302to the provider's sign-in page, asking for thescopeyou wrote and naming theredirect_urithe provider sends it back to. - The cookie in that answer
- The answer sets the
gateway_sessioncookie, markedSecureandHttpOnly, 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 inX-ID-Tokenand the user information inX-Userinfo. - What your backend reads about the person
- Decoded from Base64,
X-UserinfoandX-ID-Tokenare JSON objects of the provider's claims about the person, such aspreferred_username;X-ID-Tokenalso names the provider iniss.
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 byX-Userinfo. - To sign people out, set Logout path to a path this route serves,
/orders/logouthere. 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
Authorizationheader, and a token that lacks a scope under Required scopes is answered 403.
Related
- Serve HTTPS with your certificate: the HTTPS address the session cookie needs.
- Let a browser app call the API: a web application on another origin that calls the API.
- Require an API key: the lock for API clients, which do not sign in at a provider.
- Authentication: why people who sign in at a provider are not consumers.
- openid-connect in the reference.