Keycloak Quarkus Angular demo showing:
- UI uses
OpenID Connect
andOAuth2
usingpublic
access type (no secret in ui code required). This involvesAuthorization code grant with PKCE
- https://devansvd.com/oauth/#authorization-code-grant-with-pkce angular-oauth2-oidc
- Angular, OIDC OAuth2 - https://github.com/manfredsteyer/angular-oauth2-oidcCode
flow andPKCE
to align with the current draft of the OAuth 2.0 Security Best Current Practice document - https://tools.ietf.org/html/draft-ietf-oauth-security-topics-14Pixy
- RFC 7636 - Authorization Code Grant with PKCE (Proof Key for Code Exchange by OAuth Public Clients) - https://tools.ietf.org/html/rfc7636- Server uses
OpenID Connect
andOAuth2
usingconfidential
access type (client secret required) withquarkus-keycloak-authorization extension
- https://quarkus.io/guides/security-keycloak-authorization - OAuth 2.1 draft has a number of changes that we would like to follow - https://tools.ietf.org/html/draft-parecki-oauth-v2-1-01#section-12
Angular client uses APP_INITIALIZER
to initiate auth module and components and login to the quarkus
realm in keycloak prior to loading.
The Auth Guard
and Auth Interceptor
components map roles
to component uri's see the app-routing-module.ts
for usage.
In Quarkus, Keycloak is responsible for managing the roles and deciding who can access which routes. See the Keycloak backend-serivce
client Authorizations
tab for policy and permission details. The server side extension fetches resources on-demand from Keycloak where their URI are used to map the resources in your application that should be protected.
There is no TLS configured (this is on purpose to keep auth code clear, obviously don't do this in production! and we need TLS to be able to use all OAuth 2.1 best practices like server constrained key rotations)
Start Keycloak
podman-compose up -d
Browse to Admin Console and login as admin/admin
http://localhost:8180
Select Master -> Add Realm -> Select File
to create quarkus realm
quarkus-realm.json
Start API Server
cd service
mvn quarkus:dev
Start Angular UI
cd ui
npm i
npm run start
User/Login and Roles in quarkus realm
admin / admin - roles [admin, user]
alice / alice - roles [user]
Use the UI broswer links and the browser console (F12 developer tools in chrome) for debug.
The User Interface has 3 angular components, each calls a service API XMLHttpRequest endpoint, which is displayed in console.log
admin - localhost:8080/api/admin
user - localhost:8080/api/users/me
public - localhost:8080/api
alice
will be able to see theUser and Public Component
endpoints but not be able to browse to theAdmin Component
endpoint.admin
user can browse to the all component endpoints.- anonymous acess is available to the public api endpoint.
Unauthenticated access to admin, user endpoints will result in:
http localhost:8080/api/admin
HTTP/1.1 401 Unauthorized
content-length: 0
The public endpoint is always available e.g. from cli:
http localhost:8080/api
HTTP/1.1 200 OK
Content-Length: 15
Content-Type: application/json
{
"userName": ""
}
CLI example request using curl
or http
client:
# Login
export access_token=$(\
curl -s -X POST http://localhost:8180/auth/realms/quarkus/protocol/openid-connect/token \
--user backend-service:secret \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'username=admin&password=admin&grant_type=password' | jq --raw-output '.access_token'
)
# curl
curl -v -X GET \
http://localhost:8080/api/admin \
-H "Authorization: Bearer "$access_token
# or use http
http localhost:8080/api/admin "Authorization: Bearer $access_token"
# Authenticated Result
HTTP/1.1 200 OK
Content-Length: 20
Content-Type: application/json
{
"userName": "admin"
}
If you wanted to completely turn off authentication in the quarkus api server, set these in application.properties
:
quarkus.keycloak.policy-enforcer.enable=false
quarkus.keycloak.policy-enforcer.paths.api.path=/api/*
quarkus.keycloak.policy-enforcer.paths.api.enforcement-mode=DISABLED
Currently the Angular UI flow initializes by directing to Keycloak first before loading anything (common for Single Page Web Apps), the public api is still accessible anonymously.