IDP initiated SSO from Google SAML with Keycloak as identity broker - spring

We have Google SAML SSO login (IDP) in our Spring boot application (SP) with Keycloak as IDP broker. The SP initated login (SpringApp -> keycloak -> GoogleSSO -> keycloak -> Spring) works fine. However, if I login to my google account and click my saml application tile from the google app menu, the SSO fails at ACS endpoint with the below error.
Below error is logged inside keycloak server logs.
ERROR [org.keycloak.services.resources.IdentityBrokerService] (default
task-424) invalidRequestMessage
WARN [org.keycloak.events] (default task-424)
type=IDENTITY_PROVIDER_LOGIN_ERROR, realmId=****-realm,
clientId=null, userId=null, ipAddress=x.x.x.x,
error=invalidRequestMessage
Keycloak Identity Provider Configuration
Created new SAML v2.0 Identity provider from Identity providers menu.
Redirect URI : https://{keycloak-root}/auth/realms/{realm-name}/broker/{alias}/endpoint
First Login Flow: first broker login
Service Provider Entity ID: https://{keycloak-root}/auth/realms/{realm-name}
Single Sign-On Service URL: {google idp sso url}
Keycloak Client Configuration:
Created a new keycloak client for sso.
Client Protocol: SAML
Signature Algorithm: RSA_SHA_256
Name ID Format: Username
Valid Redirect URIs: {spring-boot-app-url} after successful authentication from google and keycloak
IDP Initiated SSO URL Name: {app-name-string}
IDP Initiated SSO Relay State: {spring-boot-app-url}
Assertion Consumer Service POST Binding URL: {spring-boot-app-url}
Google SAML App Configuration:
Entity ID: https://{keycloak-root}/auth/realms/{realm-name}
ACS URL: https://{keycloak-root}/auth/realms/{realm-name}/broker/{alias}/endpoint
Please suggest if any configuration changes has to be made to make idp initiated login work.
UPDATE:
We compared the saml request of both SP and IDP login. In IDP login, on successful redirection from google to keycloak ACS url, we found the RelayState parameter is empty. But in SP login, same RelayState parameter has a string value present, which changes on every login.
We could set a default value for RelayState using the Start URL field inside Google SAML app. But the problem is keycloak generates this value dynamically that changes on every login request.

Related

Use OAuth2 for authorization of session-authenticated users

I'm developing a microservices application that has to authenticate users against an external Identity Provider using SAML2 protocol.
The architecture
The idea is to use a SPA running in the browser which only talks to the API Gateway and uses Cookies for authentication.
The gateway delegates the Authorization Server to check if each request is authenticated and initialize the SAML2 login if not.
Once the user authenticates, the Authorization server initializes a session and sends back the cookie straight to the browser.
The Authorization Server is actually an OAuth2 Auth Server as well as a SAML2 Service Provider.
For every request coming after the user authenticated, I want internal communications to use OAuth2.
Frameworks used
For the authorization server I'm using the Spring Authorization Server package as well as SAML2 Service Provider libraries of Spring Security.
Resource services would use Spring Boot OAuth2 Server library.
What's working
I managed to set up the SAML2 client so that the Authorization Server is already generating a Session for the user after IdP authentication and I'm capable of reading the authenticated principal.
The problem
For the upcoming requests I want the API Gateway to perform a token replacement by exchanging the Cookie for an OAuth2 access token before forwarding these requests to resource services. Each resource service will then validate these tokens against the authorization server.
What I'm trying to achieve here is to make the API Gateway as a Backend-for-Frontend but the I'm struggling to figure out which authorization flow to use given that:
the client is the API Gateway, so it can be considered confidential
user credentials are missing as they are provided to an external IdP and the principal comes from a SAML Response
the authorization server has already estabilished a session for the user
Basically I can't figure out how to exchange the JSessionID for an authorization code.
Any ideas?
You should not bother about the authentication-code, the BFF (gateway configured as OAuth2 client) should receive it and exchange it for tokens (access, ID and refresh) during login process and store those in session (which should be activated along with CSRF protection).
When requests land on the gateway, session is replaced with Bearer access-token (kept in session) before being forwarded to resource-server. This behavior is activated with the tokenRelay filter in route properties (if I remember well...)

Keycloak - Authorization Request with Signed Jwt

I'm setting up a service with Keycloak as Auth Server, and I want to use "Signed Jwt" as Client Authenticator, so far, I was able to connect the microservice using a keycloak adapter with the information provided by keycloak.json, let me go into more details first:
Keycloak (12.0.4), self hosted:
A "Demo Realm"
A client name "springboot-microservice-test"
The "Client Authenticator" it's "Signed Jwt"
JWKS it's exposed and reachable on the microservice.
Some Users with roles that can get access to "springboot-microservice-test", lets call them "user_test" with "user_test_password"
Keycloak Credentials setup
Spring boot Microservice:
keycloak-spring-boot-starter, version 12.0.4
Settings defined in application properties.
Keystore file on resources folder: test_key_store.jks
Spring boot application.properties
On a previous test, with "Client ID and Secret" as Client Authenticator, I had no issues retrieving a token from keycloak and getting access to the microservice, but I couldn't find any information on how to request the access token on "Signed Jwt"
Setup with client_id and client_secret
Anyone can help me?

Spring Security and OneLogin Token Expiration

I am trying to configure an authentication flow in Spring Boot using OneLogin SSO. I can successfully authenticate, create a JWT token, and redirect to my frontend app.
However, I am not certain of the next steps. When my JWT token expires, is the appropriate course to clear my security context and then to redirect to OneLogin again and reconfirm my authentication? Right now, as far as I can tell, Spring's security context represents one moment in time and I can't figure out how to refresh it against my SSO provider to ensure the user is still authenticated.

How does the authorization rules are validated by keycloak authorization server using spring rest adapter

I have set up the keycloak server and created the spring rest application with keycloak rest adapters. The Authorizations rules are working fine.
I would like to know about the internal working of the keycloak spring boot rest adapter. How the logged in user's token is validated against policy and permission set in keycloak admin client.
You are correct, access token does not contain all these details.
In Keycloak when you are using server side adapters the client will be configured to use the standard flow and not the implicit flow of OIDC.
In standard flow when you login using keycloak IDP your front-end redirects to Keycloak IDP and asks for you credentials. If you have the right credentials login is successful and you are redirected back to your app. In this redirect your app gets a code which it then sends to the back-end rest call. This code is used by spring adapter in the spring boot app to make a call to Keycloak IDP server and it is this call in which the boot application will get the user context to take all the authorization decisions as a response from the Keycloak server.
Hope this makes sense.

Spring sso oauth2 client unable to request for access token

on spring boot 1.4, using #EnableOAuth2Sso for sso client and a kong third party authorization server, i'm able to receive the authorization code but unable to retrieve the access token.
the authorization code is part of the redirect url after which is there any configuration or a process for retrieving the access token?
Once you get the Authz code, you need to make a server side call(so that access token flow doesn't go through end user browser) to Authz Server for access_token, Look at this section of OAuth 2.0 Spec.

Resources