i've got following setup:
Frontends are Angular1 Frontends. Backend is Spring Boot in use with the Keycloak Sring Boot Adapter in Combination of Spring Security.
The process is the standard OAUTH2:
Frontend sends credentials to Keycloak
If valid Keycloak sends Token to Frontend
Frontend sends requests with this token to backend
Backend sends token to keycloak for validation
keycloak accepts token after validation
backend is responding to frontend
This is working fine with one Frontend. You have to config the Keycloak Adapter of the Spring Backend via "keycloak.auth-server-url" in application.properties. My keycloak.auth-server-url of the Keycloak Adapter is pointing to an WebServer which is delivering the Frontend1 and is configured as reverse proxy. So it is forwarding in step 3 to the keycloak server with this config:
keycloak.auth-server-url=www.UrlOfFrontend1.com/auth
'/auth' is the forwarding path to keycloak. It is working fine for one frontend.
My problem is step 4 with two frontends. Every Frontend is delivered by a own WebServer which is configured as reverse proxy. If i deliver a second frontend with a second reverse proxy which delivers Frontend2 keycloak is throwing the error:
[org.keycloak.adapters.BearerTokenRequestAuthenticator] (default
task-39) Failed to verify token:
org.keycloak.common.VerificationException: Invalid token issuer.
Expected 'http://www.UrlOfFrontend1.com/auth/realms/myrealm', but was 'http://www.UrlOfFrontend2.com/auth/realms/myrealm'
at org.keycloak.TokenVerifier.verify(TokenVerifier.java:156)
at org.keycloak.RSATokenVerifier.verify(RSATokenVerifier.java:89)
I need the Spring Boot Keycloak Adapter configuration for both frontends. I have got two public Frontend Clients in Keycloak configured. What am I missing?
Related
So I'm migrating some Spring Boot microservices from Kubernetes to OpenShift. Below is the simplified situation:
Service 1: Spring Boot application that handles, exposes 2 endpoints (login and authenticate). The authenticate service accepts the Authorization header containing a JWT token and validates that token. It returns 400 if the token doesn't exist and 403 is the user isn't authorized or the token is invalid and 200 if everything is valid.
Service 2: Spring Boot for some business service, exposes many endpoints and contains the annotation below in the Kubernetes Ingress so that all traffic is routed to the Service 1 for authentication before actually reaching Service 2
nginx.ingress.kubernetes.io/auth-url: "http://service1/authenticate?url=$request_uri&method=$request_method"
The problem is that when I migrated to OpenShift, all applications are working fine but the annotation that should route traffic to Service 1 doesn't seem to be working, since the authenticate service is never called.
I have searched the OpenShift documentation for days with no success, so any help would be much appreciated.
Probably this could help https://docs.openshift.com/container-platform/4.5/serverless/networking/serverless-ossm-jwt.html, Openshift ServiceMesh include Istio. Here is how to configure Istio JWT https://istio.io/latest/docs/tasks/security/authorization/authz-jwt/. So there you could configure the Service 1 authenticate.
Our stack includes the following services, each service runs in a docker container:
Front-end in React
Backend service based on Spring boot "resource-service"
Keycloak
Other backend service (consumer)
Both the front-end and the consumer services communicate with the backend using REST API.
We use Keycloak as our user management and authentication service.
We would like to integrate our Spring based service "resource-service" with Keycloak by serving both web application and a service flows:
Web application - React based front-send that should get a redirect 302 from the "resource-service" and send the user / browser to login in the Keycloak site and then return to get the requested resource.
Server 2 Server coomunication - A server that need to use the "resource-service" API's should get 401 in case of authentication issues and not a redirection / login page.
There are few options to integrate Spring with Keycloak:
Keycloak Spring Boot Adapter
Keycloak Spring Security Adapter
Spring Security and OAuth2
I noticed that there is a "autodetect-bearer-only" in Keycloak documentation, that seems to support exactly that case. But -
There are a lot of integration options and I'm not sure what is the best way to go, for a new Spring boot service.
In addition, I didn't find where to configure that property.
I've used approaches one and two and in my opinion, if you are using Spring Boot, use the corresponding adapter, use the Spring Security adapter if you're still using plain Spring MVC. I've never seen the necessity for the third approach as you basically have to do everything on your own, why would anyone not use the first two methods?
As for using the Spring Bood adapter, the only configuration necessary is the following:
keycloak:
bearer-only: true
auth-server-url: your-url
realm: your-realm
resource: your-resource
And you're done. The bearer-only is so that you return 401 if a client arrives without a bearer token and isn't redirected to a login page, as you wanted. At least that's what's working for us :-)
After that, you can either use the configuration for securing endpoints but it's a bit more flexible to either use httpSecurity or #EnableGlobalMethodSecurity which we're doing with e. g. #Secured({"ROLE_whatever_role"}).
If you're using the newest Spring Boot version combined with Spring Cloud, you might run into this issue.
I configure my resource-servers to always return 401 when Authorization header is missing or invalid (and never 302), whatever the client.
The client handles authentication when it is required, token refreshing, etc.: Some of certified OpenID client libs even propose features to ensure user has a valid access-token before issuing requests to protected resources. My favorite for Angular is angular-auth-oidc-client, but I don't know which React lib has same features.
Keycloak adapters for Spring are now deprecated. You can refer to this tutorials for various resource-server security configuration options. It covers uses cases from most simple RBAC to building DSL like: #PreAuthorize("is(#username) or isNice() or onBehalfOf(#username).can('greet')")
I am using Spring cloud with OAuth2. I have 4 applications as mentioned below:
1) Eureka server : Service Registery.
2) zuul as Api Gateway
3) Auth server - which is returning the access_token to client after successful authentication.
4) Resource server - wants to validate token before giving access to resource.
I used the below configuration in application.properties:
security.oauth2.resource.tokenInfoUri=http://localhost:9600/oauth/check_token
security.oauth2.client.client-id=resourceServer-client
security.oauth2.client.client-secret=secret
I dont want to give hard coded ipaddress / hostname for "tokenInfoUri" in application.properties.
I want to access the auth server by its service name as there can be multiple instances of Auth server.
How can i do that ?
I checked the code how tokenInfoUri works in spring boot using oauth2 and found that
ResourceServerTokenServicesConfiguration -> RemoteTokenServicesConfiguration -> remoteTokenServices()
method where tokenInfoUri us retrieved from ResourceServerProperties.java as #ConfigurationProperties.
I dont want to use JWT token for token verification. I want to verify using remote call from Resource Server to AuthServer.
I'm currently working on a project that uses Zuul to proxy requests to both API endpoints as well as client resources. There is an angular app that is being served from the same endpoint as the Zuul proxy as outlined in this guide. I have the need for additional clients, specifically a desktop application.
I'm not sure I understand how Zuul proxy handles requests and I think there are several paths to get to where I want to go, I'm just not sure what the correct one is.
Here is what I have surmised thus far:
Option 1: Extract the Zuul proxy and SSO capabilities to it's own server. Then create a new UI server which is behind the gateway server. Follow this up with creating a new client application server which handles the authentication of the desktop client.
Option 2: Extract the Zuul proxy and SSO capabilities to it's own server. Serve the current angular app from its own server NOT behind the proxy and change the authorization flow to something different (implicit). Alter Zuul proxy and SSO configuration to ignore requests that already have a bearer token in the header.
If I go with option 2 then I don't understand how to register with the Zuul gateway client that I already am providing the authorization header with my requests so all it should be doing then is proxying my requests to the correct microservices.
Final Questions:
Which option is the most optimal one?
If an access token is already acquired (directly from the auth server using implicit flow) then how does Zuul need to be configured to not try and acquire the access token using the jsessionid?
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.