Quick Look at Authentication with Keycloak
16836 단어 openid_connectauthenticationKeycloak
I've just started taking a look at it, so I will write about how I tested OpenID Connect's (OIDC) Authorization Code Flow using Keycloak as the authorization server. This is a very common flow we see when applications allow us to login with our Google or Facebook credentials.
Explaining OpenID Connect is not the goal of this article, so I will leave an extremely succinct and well explained article about the subject:
https://www.simpleorientedarchitecture.com/openid-connect-in-a-nutshell/
Running Keycloak
I've run Keycloak on Docker on my local machine. Make sure Docker is installed and start Keycloak with the following command (please adapt it to your needs):
$ docker run -d --name=keycloak --restart unless-stopped -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2
Just access http://localhost:8080 to be presented with the welcome page:Just click on Administration Console and you can login with username
admin
and password admin
as set in the Docker command. In this console, we can add users and register applications to be secured by Keycloak.Realms
A realm represents the top level grouping mechanism in Keycloak. It is a space where we can create isolated groups of users and applications. By default, we have the
master
realm that contains the admin user we used to login to the console. But, we should not use it for our own applications and only use it to create other realms.So, let's create our realm by hovering over the
Master
menu and clicking Add realm
:Type
demo
in the Name field and click Create
.Users
Let's create a user in the newly created realm. Click
Users
in the sidebar and then Add user
in the top-right corner of the page.And create a user as shown in the image above. In the user details, select the
Credentials
tab to set its password. We can disable the Temporary
option to make it permanent since we are just testing the functionality. If this is enabled, the user needs to set a new password after logging in.Clients
Now, we're going to create a new client. Clients are the applications that will use Keycloak as their authentication system. Click
Clients
in the sidebar and Create
in the top-right corner of the page.And add a client called
test_client_app
as shown above. I've set an arbitrary Root URL
since I just want to simulate the login flow without actually having an application for that.We want to make sure the
Standard Flow Enabled
option is turned on to make sure we can use the Authorization Code Flow. Let's also enable the Consent Required
option, so the end-user needs to explicitly consent to sharing his/her information to the client application. Also, set Access Type
as confidential
, so our client application needs to provide a secret when interacting with the OIDC endpoints.Testing the Authorization Code Flow
We can finally test the Authorization Code Flow. Here, we are simulating the user we created clicking in the login button in the test_client_app. A client app will redirect the user to a link like below, the authorization endpoint, so the person can login to Keycloak. For our test, let's open this URL in the browser.
http://localhost:8080/auth/realms/demo/protocol/openid-connect/auth?client_id=test_client_app&response_type=code&state=a_random_state_to_validate_the_callback
Then we can type our credentials to sign in:The consent screen will be displayed as we are used to when using Google or Facebook to login to other services.
Clicking
Yes
will redirect us to an error page. This is expected since Keycloak redirect us to the Root URL
we configured previously and we don't have an actual client application to test. The URL of the page we are redirect to will be something like below:http://localhost:9090/?state=a_random_state_to_validate_the_callback&session_state=f526307d-8bf0-4706-b308-2309ddc1c95a&code=25f7896f-12ef-499b-a8eb-85364e068379.f526307d-8bf0-4706-b308-2309ddc1c95a.b0f608c3-ccd2-4923-9ade-f785c6237cc3
state
is the random value we set when accessing the login page. Our client application can check it now to make sure it matches the initial request. The most significant parameter here is the code
parameter we can exchange by an access token.Access Token
We can exchange the
code
received previously by an access token. We do that by making a request to the token endpoint. To check the available endpoints in our realm, we can open the following URL in the browser. This is the identity provider metadata endpoint.http://localhost:8080/auth/realms/demo/.well-known/openid-configuration
So, to call the token endpoint, let's run the following request in a terminal:
curl -X POST 'http://localhost:8080/auth/realms/demo/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d 'client_id=test_client_app' \
-d 'client_secret=9797d273-a3e2-4269-85b6-6deec57bdc40' \
-d 'code=25f7896f-12ef-499b-a8eb-85364e068379.f526307d-8bf0-4706-b308-2309ddc1c95a.b0f608c3-ccd2-4923-9ade-f785c6237cc3' \
-d 'redirect_uri=http://localhost:9090/callback'
The client_secret
can be found in the Credentials
tab in the client details page as below, if the Access Type
was set to confidential
as described in the initial steps.The response will be a JSON and contain the
access_token
:{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICItUHVFWHk4N09ucko5OFpzZjRXRlEyY1VhTmFlQ2JtTXFxSGY5TnpRVEdNIn0.eyJleHAiOjE2Mzg0NjAzMzIsImlhdCI6MTYzODQ2MDAzMiwiYXV0aF90aW1lIjoxNjM4NDYwMDA0LCJqdGkiOiIyMmY5MDg5Mi01MDE1LTRiMmItYjkxNS03YWEyYTlkZGRhMmUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvZGVtbyIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJjMjk2N2JmNy0zYmFmLTQzYzQtOGFlYS1kZmVlZDAxODUyZWIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZXN0X2NsaWVudF9hcHAiLCJzZXNzaW9uX3N0YXRlIjoiODQzYWM5NWUtOTE5YS00ZmVhLTlkM2QtODhiMzY0MjRlZmI3IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjkwOTAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwiZGVmYXVsdC1yb2xlcy1kZW1vIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiI4NDNhYzk1ZS05MTlhLTRmZWEtOWQzZC04OGIzNjQyNGVmYjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJUZXN0IFVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0X3VzZXIiLCJnaXZlbl9uYW1lIjoiVGVzdCIsImZhbWlseV9uYW1lIjoiVXNlciJ9.g_v6DA9foM1TBUUV46wclDbkSYrFWJ1S6VWXuA1lj6AY1T4SIFcGrGDibCdT1N1s01HsU1qDwJohLcQpBmojIbgeLHuIK_K2AeDC99lE0yVFvxxoH-rfeAyHDJf0Vqqk_GWQU0hl3VYhDEb-ZBstkFwv0Vuu1C9nw6a_w1POoEACMppz-0WROeXhQa5_D8yqGHSC70jZ0vUVFCL7RiVeXDaV9J7kyoSr4bQYhJ1bHU9kQwq-yo0eSLxCnmQmYFa3yEDJKSCTups7A1FrXTuNTG8XUT1pfa_YVh51g4_u_HEsahwl8mSSs_Y56TLI5LNOBKj-tH56aDxCoLx8XMWYJQ",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyYmUwYjMxYS0wZTUwLTQzMWEtYjZiNi1jMmJkZDFhZDk0MTgifQ.eyJleHAiOjE2Mzg0NjE4MzIsImlhdCI6MTYzODQ2MDAzMiwianRpIjoiOGJlYjA5NDktODRkYi00NzI1LTlmN2MtMjc0YzU5NWFmYzkxIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL2RlbW8iLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvZGVtbyIsInN1YiI6ImMyOTY3YmY3LTNiYWYtNDNjNC04YWVhLWRmZWVkMDE4NTJlYiIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJ0ZXN0X2NsaWVudF9hcHAiLCJzZXNzaW9uX3N0YXRlIjoiODQzYWM5NWUtOTE5YS00ZmVhLTlkM2QtODhiMzY0MjRlZmI3Iiwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwic2lkIjoiODQzYWM5NWUtOTE5YS00ZmVhLTlkM2QtODhiMzY0MjRlZmI3In0.sDfZRV6snD8wGkSZ1h-Asn2FFXDS0DPAXKUss4WgBos",
"token_type": "Bearer",
"not-before-policy": 0,
"session_state": "843ac95e-919a-4fea-9d3d-88b36424efb7",
"scope": "email profile"
}
UserinfoNow that we have an access token, we can use it to make a request to the userinfo endpoint:
curl 'http://localhost:8080/auth/realms/demo/protocol/openid-connect/userinfo' \
-H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICItUHVFWHk4N09ucko5OFpzZjRXRlEyY1VhTmFlQ2JtTXFxSGY5TnpRVEdNIn0.eyJleHAiOjE2Mzg0NjAzMzIsImlhdCI6MTYzODQ2MDAzMiwiYXV0aF90aW1lIjoxNjM4NDYwMDA0LCJqdGkiOiIyMmY5MDg5Mi01MDE1LTRiMmItYjkxNS03YWEyYTlkZGRhMmUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvZGVtbyIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJjMjk2N2JmNy0zYmFmLTQzYzQtOGFlYS1kZmVlZDAxODUyZWIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJ0ZXN0X2NsaWVudF9hcHAiLCJzZXNzaW9uX3N0YXRlIjoiODQzYWM5NWUtOTE5YS00ZmVhLTlkM2QtODhiMzY0MjRlZmI3IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjkwOTAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwiZGVmYXVsdC1yb2xlcy1kZW1vIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiI4NDNhYzk1ZS05MTlhLTRmZWEtOWQzZC04OGIzNjQyNGVmYjciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJUZXN0IFVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0X3VzZXIiLCJnaXZlbl9uYW1lIjoiVGVzdCIsImZhbWlseV9uYW1lIjoiVXNlciJ9.g_v6DA9foM1TBUUV46wclDbkSYrFWJ1S6VWXuA1lj6AY1T4SIFcGrGDibCdT1N1s01HsU1qDwJohLcQpBmojIbgeLHuIK_K2AeDC99lE0yVFvxxoH-rfeAyHDJf0Vqqk_GWQU0hl3VYhDEb-ZBstkFwv0Vuu1C9nw6a_w1POoEACMppz-0WROeXhQa5_D8yqGHSC70jZ0vUVFCL7RiVeXDaV9J7kyoSr4bQYhJ1bHU9kQwq-yo0eSLxCnmQmYFa3yEDJKSCTups7A1FrXTuNTG8XUT1pfa_YVh51g4_u_HEsahwl8mSSs_Y56TLI5LNOBKj-tH56aDxCoLx8XMWYJQ'
This returns details about the user as expected so, in a real application, we could proceed to registering or logging in the user.{
"sub": "c2967bf7-3baf-43c4-8aea-dfeed01852eb",
"email_verified": false,
"name": "Test User",
"preferred_username": "test_user",
"given_name": "Test",
"family_name": "User"
}
This was a very short test of Keycloak. It's extremely fully-featured and flexible, so I plan to learn more about it since it seems to be a very good option to have in our toolkit.References
Reference
이 문제에 관하여(Quick Look at Authentication with Keycloak), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/dennistanaka/items/f7bd097e46eb2c13fe68텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)