I have a React front end
connected to a Keycloak server. I click on the login button and I'm redirected
to the Keycloak login form. Now, I can call my microservices architecture to read the protected
data behind a Spring Gateway application. Here it is. The OAuth2 protocol has different behaviors
depending on the client's used. But I can't use the same workflow for the backend authentication
then from the front-end authentication. Let's see in details. I have a backend server which requires
to access protected data. But this protected data is behind an OAuth2 authorization server. When the
backend tries to access the protected resources, it will receive a login page. I must show this
login page to the final user. Once authenticated, the backend can access the protected resources.
Until here, it's okay. I've already done a video about that. Check the link in the corner. But the
front end can't have the same workflow. Let's see why. Let's go back to the initial step, when the
authorization server returns the login page from the backend. The authorization server returns a
login form because it already knows the backend, because it already trusts the back end. How to
create this trust? I first need to register my backend in the authorization server. Then, the
authorization server returns me a client_id and a client_secret. I must store them in the backend.
I need those two keys to talk to the authorization server. But what if I change my backend to a front
end. I can't store the client_id and secret in the front end. As the user will download the front
end in the browser. Anyone could read those keys. The previous workflow is the authorization
code flow. But when using public clients, like a React application or a mobile application, I need
another layer, I need the PKCE authorization code flow. PKCE stands for Proof Key Code Enhanced
authorization code flow. Now, while registering my client in Keycloak, I indicate a hashing
algorithm. When starting the communication, the front end will create a random string as
a code verifier. The front end will encode the code verifier and send it to Keycloak when first
asking for the login page. Keyclock will decode it and store the original code verifier. If the
login is successful, the front end must ask again for the access token. And this time the
front end must send to original code verifier. Keycloak will check if it's ok and respond with
the access token. The front end can use now the access token to request the protected resources.
Why it is secure now? Because it's Keycloak which request the callback. So, even if I try to send
a request by my own, with the client_id and the encoded code verifier, I won't have the call
back to my application. And I won't receive the access token. Ok. So, what must I change in
my application now? The resources server still need to connect to Keycloak to validate the
access token received from the request. The API Gateway needs no more OAuth2 configuration.
All is moved to the front end. For the front end, I can call the specific endpoints of Keycloak
manually. But I would rather use a library for that. And finally in Keycloak, I must register
my front end as a public client, with PKCE. Let's see it. I start with the project used in my
previous video, where I connect the API Gateway with Keycloak. As said I need the configuration
to connect my resources server with Keycloak. I indicate the URL of Keycloak.
And in the security configuration I indicate which scopes are necessary
for each endpoint. And the controller stays simple. I need no more OAuth2
configuration. Let's go now with the API Gateway. Here, I need to remove all the security
configuration, as I move it to the front end. Now, as I have a front end
connected to the API Gateway, I need to configure the CORS
to avoid the usual problems. That's all. API Gateway clean. Let's move to
Keycloak. Let's create now my front-end client. I leave those options disabled. The client
authentication off means that the client is a public server. If I enable it, I will
get a client_id and a client_secret. And I don't want a secret. The authorization is
for fine-tuned authorization. I don't need this. I leave the rest of the options. The only
one which interests me is the standard flow. I will now add the callback URL This is the one which will make
the second request automatically. And I must add the web origins to
allow my front-end access Keycloak. Let's go now to the advanced settings. If I scroll down, I can
see the PKCE configuration. I choose the algorithm to use and that's all. Finally, I create
my scope and add it to my client. That's all. Let's finish with the front end. As said I can do it all by requesting
the Keycloak endpoint, but it's a lot of hard coding and there are some libraries
which will do it for me. Let's use this one. Wait, wait oidc or OAuth2? The OAuth2 is the
original authentication Protocol. And oidc or Open ID Connect is a layer over OAuth2. oidc
allows me to get all the necessary information at once. This way I avoid requesting Keycloak
each time I need to read protected resources. I have already created a front-end application.
I wrap all in a component called App. Here is the Header component. And this is the
AppContent component. Then I have the Toaster component. Which are the popins
which display some temporary information. It's another library I use. I have then
the Buttons component which wraps those buttons. And finally the AuthContent component.
I don't see it now because I'm not authenticated. All I need is to create two helpers. One
to talk with Keycloak and the order to talk with the backend. Let's start with the
authentication helper, to talk with Keycloak. This is the URL of Keycloak. The client_id I've configured in Keycloak. The callback URL I've configured in Keycloak. This is to request the access token. I
don't want a cookie or something else. Here, I must specify the scope I want: the open ID
and the profile as I want to display the username This first method is to read the user
object stored in the local storage. This method doesn't read it from Keycloak.
I must first log in to use this method. This will perform the login. It will redirect
the end user to the login page of Keycloak. Finally, the logout method. All those methods are already connected to the
buttons. Let's see what I do in the callback page. Here, I only call the signinRedirectCallback,
which will receive the user object and store it in the local storage. This way, it's
accessible for further requests. Let's continue with helper to talk with the back end,
which is using axios but with the access token. When calling the backend, I need the access token. This access token is the JWT to use
in the HTTP header of the requests. I only call the backend if I've already logged
my user, if I've already an access token. Let's see now how it works. When I click on the login
button, I'm redirected to the Keycloak login page. Here is the endpoint which returns
me the Keycloak login page. It contains the client_id, the redirect URL, the scopes and the code challenge,
which is the encoded code verifier. When logged correctly, I have the sign in
callback, I have the callback URL which is called. And I have the user loaded in my
local storage. Now, I can call the back end which returns me to protected resources. In the
back end request I can see now the access token sent in the Authorization Header. Okay, let's
make a quick recap. I've removed the configuration from the API Gateway. I've connected my resource
server to Keycloak. I've created a public client with PKCE in Keycloak. I've added the library
oidc-client to my front end. I've configured my oidc object with the client_id, the Keycloak
URL, the callback URL and the scopes. After logging for the first time, I've used the received
access token for all the requests to the back end. That's all for this video. I've also done other
videos about the OAuth2 protocol, as a backend server alone, with Keycloak, with GitHub connect,
or with a simple JWT. Feel free to watch them all. And of course, click on the like button and
subscribe to my channel. And see you soon. Bye!