Reputation: 43
I'm writing a backend implementation of authentication in an external sso. I use Spring Boot 3 for microservices, Keycloak is responsible for authentication. Keycloak contains multiple realms to support multi-tenancy. Our services and front use jwt tokens for authorization, so as a result of sso authentication we should receive a token of our Keycloak.
Expected implementation:
** I tried using the keycloak account client URL to go to the sso form, the Keycloak itself substitutes its URL in the redirect_uri and the authentication is successful, but this is not what I need, because the frontend already has a login form.
My question is: What should the link in step 3 look like, which the “auth” microservice will call in Keycloak? What needs to be inserted into the redirect - the original front URL, the Keycloak URL or the external sso endpoint? How can I return Keycloak token?
I compose it like this: {keycloakUrl}/realms/{realmName}/protocol/openid-connect/auth?client_id={clientId}&redirect_uri={???}&response_type=code&scope=openId&kc_idp_hint={alias}
Upvotes: 0
Views: 773
Reputation: 12835
The solution you imagine goes against the current recommendations and breaks several OAuth2 rules.
frontend calls “bff” (backend for frontend) microservice, passing the user’s login as input
This is not how OAuth2 works. In OAuth2 authorization code flow, which is the only recommended flow for user login, neither the frontend nor your OAuth2 client should have access to users credentials. Only the authorization server does (in your case, Keycloak or the IDP behind it).
redirect the user to the external IDP page, bypassing the Keycloak form
With Keycloak, this is done by providing a kc_idp_hint
parameter with the authorization request.
redirect back to the original frontend page along with the jwt token
According to the latest recommendations, OAuth2 tokens should not leave your servers. Communications between the front and back ends should be authorized with session cookies (and protection against CSRF). The BFF keeps tokens in session and replaces the session cookie with a Bearer token when forwarding requests. I wrote an article for that at Baeldung.
Provided that the BFF is a Spring Cloud Gateway instance:
authorization_code
for each "tenant" (a minimum of one per provider, more if you want Keycloak authentication plus some "direct access" to external IDP(s) for each realm)TokenRelay=
filter on the BFF replaces the session cookie with the Bearer token in sessionI maintain a Spring Boot starter to help configure the BFF (protection against CSRF using cookies accessible to the front-end code, saving the post login/logout URLs in session, and more). Its usage is explained in the Baeldung article linked above.
Upvotes: 0