In this article we are going to get a brief introduction to the standards that enable us to integrate web applications securely and easily with Keycloak. This blog will give we a gentle introduction without going too much into detail. Even if we are new to these standards, we may still want to skim through them.
Authorizing application access with OAuth 2.0
OAuth 2.0 is by now a massively popular industry-standard protocol for authorization. At the core of OAuth 2.0 sits the OAuth 2.0 framework, which enabled a whole ecosystem of websites to integrate with each other. Prior to OAuth 2.0 there was OAuth 1, by sharing user credentials to allow thirdparty applications to access data on behalf of the user, but these approaches were complex or not easily interoperable. With OAuth 2.0, sharing user data to third-party applications is easy, doesn’t require sharing user credentials, and allows control over what data is shared. OAuth 2.0 is incredibly useful for limiting access to our own applications.
There are four roles defined in OAuth 2.0:
>Resource owner: This is typically the end user that owns the resources an application wants to access.
>Resource server: This is the service hosting the protected resources.
>Client: This is the application that would like to access the resource.
>Authorization server: This is the server issuing access to the client, which is the role of Keycloak.
In essence, in an OAuth 2.0 protocol flow, the client requests access to a resource on behalf of a resource owner from the authorization server. The authorization server issues limited access to the resource in the form of an access token. After receiving the access token, the client can access the resource at the resource server by including the access token in the request.
Depending on the application type and use case below formula can be applied:-
>If the application is accessing the resource on behalf of itself (the application is the resource owner), use the Client Credentials flow.
>Use the Authorization Code flow.
>Implicit flow: This was a simplified flow for native applications and client-side applications, which is now considered insecure and should not be used.
>Resource Owner Password Credentials flow: In this flow, the application collects the user’s credentials directly and exchanges them for an access token. In case we want the login form to be directly integrated with wer application. It is inherently insecure as we are exposing the user’s credentials directly to the application, and we will also run into other problems in the long run, when we want wer users to use stronger authentication than only a password, for example.
Within an OAuth 2.0 flow there are two client types, which are confidential and public clients. Confidential clients are applications such as a serverside web application that are able to safely store credentials that they can use to authenticate with the authorization server. Public clients, on the other hand, are client-side applications that are not able to safely store credentials. As public clients are not able to authenticate with the authorization server, there are two safeguards in place:
1. The authorization server will only send the authorization code to an application hosted on a pre-configured URL, in the form of a previously registered redirect URI.
2. Proof Key for Code Exchange (PKCE, RFC 7636), which is an extension to OAuth 2.0, prevents anyone that intercepts an authorization code from exchanging it for an access token.
In addition to the core OAuth 2.0 framework, there are a few additional specifications we should be aware of such as Bearer Tokens (RFC 6750), Token Introspection (RFC 7662), and Token Revocation (RFC 7009). There are also a number of best practices on how we should use OAuth 2.0. There are recommendations for native applications, and browser-based applications, as well as security considerations and best practices. We will cover these later in some other blog.
Authenticating users with OpenID Connect
While OAuth 2.0 is a protocol for authorization, it does not cover authentication. OpenID Connect builds on top of OAuth 2.0 to add an authentication layer.
At the heart of OpenID Connect sits the OpenID Connect Core specification, which has enabled a whole ecosystem of websites to no longer need to deal with user management and authenticating users.
As it builds on top of OAuth 2.0, it has significantly reduced the number of times a user has to authenticate, as well as the number of different passwords a user has to juggle, that is if they care about using unique passwords for all websites they access. Just think about the endless number of websites that allow you to sign in using Google or other social networks.
I’m highlighting Google rather than other social networks here due to the fact that they are actually implementing OpenID Connect properly, which makes it incredibly easy to add sign-on with Google, compared to some other sites that have done their own tweaks to OAuth 2.0 rather than implement OpenID Connect according to the specifications.
OpenID Connect has not only enabled social login but is also, of course, very useful within the enterprise in order to have a centralized solution for authentication, supporting single sign-on. This also significantly increases security as applications don’t have access to the user credentials directly. It also enables the use of stronger authentication, such as OTP or WebAuthn, without the need to support it directly within applications.
Not only does OpenID Connect enable easy authentication within the enterprise, but it also enables us to allow third parties such as employees at partner companies to access applications within your enterprise without having to create individual accounts within our enterprise.
Like OAuth 2.0, OpenID Connect defines a number of roles involved in the protocol:
- End-User: This is the equivalent of the resource owner in OAuth 2.0. It is, of course, the human being that is authenticating.
- Relying Party (RP): A somewhat confusing term for the application that would like to authenticate the end-user. It is called the relying party, as it is a party that is relying on the OpenID Connect Provider to verify the identity of the user.
- OpenID Provider (OP): The identity provider that is authenticating the user, which is the role of Keycloak.
In essence, in an OpenID Connect protocol flow, the Relying Party requests the identity of the end-user from the OpenID Provider. As it builds on top of OAuth 2.0 at the same time as the identity of the user is requested, it can also obtain an access token.
OpenID Connect utilizes the Authorization Code grant type from OAuth 2.0. The main difference is that the client includes scope=openid in the initial request, which makes it an authentication request, rather than an authorization request.
While OAuth 2.0 calls the different flows grant types, OpenID Connect refers to them as flows. There are two flows in OpenID Connect that you should care about:
- Authorization Code flow: This uses the same flow as the OAuth 2.0 Authorization Code grant type and returns an authorization code like OAuth 2.0 that can be exchanged for an ID token, an access token, and a refresh token.
- Hybrid flow: In the Hybrid flow, the ID token is returned from the initial request alongside an authorization code.
In addition to the OpenID Connect Core specification, there are a few additional specifications we should be aware of:
- Discovery: This allows clients to dynamically discover information about the OpenID Provider.
- Dynamic Registration: This allows clients to dynamically register themselves with the OpenID Provider.
- Session Management: Defines how to monitor the end user’s authentication session with the OpenID Provider, and how the client can initiate a logout.
- Front-Channel Logout: Defines a mechanism for single sign-out of multiple applications using embedded iframes.
- Back-Channel Logout: Defines a mechanism for single sign-out for multiple applications using a back-channel request mechanism.
Why I prefer to go with OpenID Connect because of two additional concepts on top of OAuth 2.0. It clearly specifies the format of the ID token by leveraging the JWT specification, which, unlike the access token in OAuth 2.0, is not opaque. It has a well-specified format, and the values (called claims) within the token can be directly read by the client. This allows the clients to discover information about the authenticated user in a standard way. It defines a user info endpoint, which can be invoked with an access token and returns the same standard claims as found in the ID token.
Understanding why SAML 2.0 is still relevant
Security Assertion Markup Language 2.0 (SAML 2.0) is a mature and robust protocol for authentication and authorization. It is very widely used to enable single sign-on within enterprises and other domains, such as education and government.
to be continued…