I'm exploring the TokenRelay filter of Spring Cloud Gateway in order to mediate between a SAML2 Session and OAuth2 Tokens (More on this in my previous question here).
I've tried to figure this out myself but I can't seem to sort it out: using this filter, who is the OAuth2 client?
I was expecting this to be the gateway itself, hence a confidential one.. but in my initial setup I see calls for the authorization code in the browser and I don't understand if this is the expected behavior or not.
If it's indeed how it's supposed to work and the Browser carries out the token exchange, does this mean that the client cannot be confidential? Should I switch to PKCE?
I might sound a little confused (I really am!) but I can't seem to find much about the matter.
Thanks!
In BFF pattern, the only OAuth2 client is the BFF itself (spring-cloud-gateway in your case), but in authorization-code flow the user authenticates with its user-agent (most frequently system browser for login forms but could be other apps for biometry or multi-factor auth). However, the authorization-code should be sent by authorization-server only to declared clients: the BFF (not the rich app in browser) which will use it to fetch OAuth2 tokens.
To be clearer (maybe):
authorization-code generation is triggered by a request from the user-agent (browser) to the authorization-server
the authorization-server sends the code to the client (spring-cloud-gateway BFF)
the client (spring-cloud-gateway BFF) uses the code to fetch tokens from the authorization-server
=> with this pattern, the browser never sees the OAuth2 tokens (nor the authorization-code).
Of course, this is not the same when the declared OAuth2 client is a public client running in the browser (code and tokens are still sent to the client but as it is running in the browser, tokens are stored in ... the browser)
Related
I'm new to security and I'm trying to understand how to implement proper security without any overkill.
Below are my questions.
I don't want to allow 3rd party clients to use my API and hence I don't see any importance of OAuth 2.0. Hence I'm looking to use the sessions generated by keycloak (or Ory Kratos) in my Spring Boot Security. Any guidance on how to do that.
I have come across an application https://opstra.definedge.com/ which security is implemented using keycloak (can see the URL pattern). But in the requests, I can't see any JWT token in the chrome DevTools Network Tab while performing any network requests. I think they are implementing it the way I wanted. Any overview on how it is implemented.
I'm not architect at definedge, but I'm pretty sure they do not use Keycloak sessions in Opstra (they would have to run Opstra inside Keycloak servlet for that). It more looks like they use OAuth2 to authenticate users from a Java client and that this client has sessions of its own enabled (JSESSIONID cookie for opstra.definedge.com VS sso.definedge.com). It is quite possible that this java client uses access-tokens to authorize requests to resource-server(s), we just can't see it from the browser.
Restricting the clients allowed to consume your API has little to do with authorization method:
with basic authorization header, any client with login and password can access
with Bearer authorization header, any client with a valid token can access (which you already had anticipated)
even JSESSIONID cookie can be set for any origin (I believe), in which condition any request from the same browser would be authorized, whatever the web client.
Restricting your API clients is more about CORS configuration, which aims at just that: filtering which origins (host + port) can access which resource location (URL)
There is a notion of confidential client in Keycloak where the client must provide a password in addition to client-id to exchange authorization codes for access-tokens, but this does not apply to rich clients (clients running on devices you cannot trust): Angular, Vue, React, native mobile apps, etc. code can be reversed enginereed to read that password. But it is possible to configure a Java client of your own as "confidential" and as so, allow this client only to get access tokens to query resource-server (API).
OAuth2 comes with much more than just easing multi-client scenarios and JWTs with session-less java applications greatly ease horizontal scalability and fault tolerance. You should read this article for a refresher on
OAuth2 (and its value)
resource-server security configuration (with CORS)
I'm having a hard time figuring a good way to implement Oauth 2.0 and OpenID Connect authentication alongside an existing internal email+password authentication for a B2B Web app's API using Spring security.
We have a backend REST API that is a Spring Boot servlet application which currently authenticates users with OAuth 1.0 and the password grant. The front-end is an Angular single-page app through which users must log in with their username and password. The API's /oauth/token endpoint then delivers an opaque access token to be used for fetching secured resources that are then displayed within the app.
We'd like to add the possibility to log in using external authentication with OpenID connect, which is a perfect opportunity for switching to OAuth 2.0 and JWT tokens. Our API would then accept JWT tokens it delivered as well as external JWT tokens emitted by accepted issuers.
Reading and validating JWT tokens won't be a problem using Spring security's OAuth Resource Server. However things get complicated with how to make the classic username+password login flow work with JWT tokens.
We thought about delivering JWT access tokens the same way we used to with our old OAuth 1.0 tokens. The thing is, newer OAuth specifications advise against using the password grant, plus it simply isn't supported in the Spring authorization server project we're planning to use. The authorization-code flow w/ PKCE seems like too much for this case as we do not want the back-end API to render a login form but use credentials entered in the existing login form that is part of the single-page app.
I've read a lot about not using OAuth for 1st party login since its primary use is for external authentication, but again, that doesn't apply since we also want 3rd party authentication.
What would be a secure way to implement a Spring boot authorization server that can deliver JWT access tokens to a 1st party client in exchange for a user's credentials, all this using the existing log in page, and given the password grant type no longer being supported?
I thought about implementing a preliminary step that would be a POST request with Basic authentication to a /login endpoint that just returns a 200 HTTP status, then proceeding to the /oauth2/authorize request that would deliver the authorization code immediately without redirecting since my session is authenticated.
I'll be happy to provide more details if needed. Here are the resources I'm using for this project.
What about setting up an authorization-server capable of identity federation?
In such configuration, the authorization-server is responsible for providing with identities, proxying one or more sources (your existing user database for instance, plus maybe Google, Facebook, Github, etc.)
Keycloak does it for instance.
From the client point of view (your Angular app), the authorization-server is used to get:
access-token: put in Authorization header of requests to secured resource-server(s) (can be a JWT or an opaque string, doesn't matter, clients should not try to extract data from access-tokens)
refresh-token: send to authorization-server to renew access-token before it expires
id-token: get user-profile data (email, username, profile picture, etc.)
You should have a look at https://github.com/damienbod/angular-auth-oidc-client for connecting an Angular app to an OIDC authorization-server.
From resource-server point of view, access-tokens are the source ofr setting-up security-context, either by decoding and validating a JWT locally or with token introspection on authorization-server.
Have a look at those tutorials for such resource-servers configuration.
There are two spring-boot apps.
client
resource-sever
there is dev okta account that is used as auth server
(those 2 apps are standard Spring Boot client -> resource-server, almost out of the box with okta setup for them, should not be problem there)
client - securely sends messages to--> secure-sever (passing the access token in the header as prove that it's authorized to call it and get data back)
(it works as expected)
But I am trying to figure out what's going on between all them, traffic wise
I'm trying to spot that moment when resource-server checks the token it got from the client that got it from the auth server.
Here is a sequence diagram of standard oauth 2.0 flow and that part that I want to debug (arrow)
auth server
And there is a communications between client, resource-sever:
There seems I can not confirm that Resource Server (from the right) does any token validation with the auth-server (okta)..?
Question: is why? From my understanding it is supposed to validate it (somehow).
I was expecting to see a call from resource-server to auth-server (otka) with the token-validation-request (ETF RFC 7662 in October 2015) like this:
How to validate an OAuth 2.0 access token for a resource server?
I was expecting, lets say, tat for every client call, resource server would check if that token the client passes is valid. Yet I do not see any calls from resource service to okta that would use the token in its requests to okta.
This comes down to the difference between JWTs and opaque tokens.
It looks like your application is using JWTs, based on the calls I'm seeing to /keys.
When using JWT authentication the resource server will query the jwks_url (in this case /keys) on startup to retrieve a set of public keys that it can use to validate the JWT-encoded bearer tokens.
Then, when the resource server receives a bearer token in a request from the client it will validate its signature against a public key obtained from the jwks_url endpoint.
This means the resource server doesn't have to query the authorization server on every request.
You can read more about this process in the OAuth 2.0 Resource Server JWT section of the Spring Security reference documentation.
The question that you linked to refers to opaque tokens.
In this setup, the resource server must call the authorization server introspection endpoint to validate the token every time.
You can read more about this process in the OAuth 2.0 Resource Server Opaque Token section of the Spring Security reference documentation.
I need to develop set of microservices (rest APIs) which is to be used by web and mobile client, the microservices are sitting behind API gateway, I've to integrate with SSO (using SAML) for user's authentication, I understand that SAML token to oAuth2 token conversion has to be done so that I can verify auth token at API gateway and handle authorization there itself, but the piece which is not clear to me is that who will take care of conversion of SAML token to oAuth2 token, is it IDP who provide this functionality out of box or do I need to built up something of my own?
One possible solution which I'm thinking of is
User (from web/mobile) sign in via SSO
Gets SAML response from IDP
Send that SAML response to server to generate Auth Token
Server gets request to generate auth token, looks for SAML response and validate it against IDP
If SAML response is valid then generate auth token and send it back to client
On subsequent API request from client the token is passed as header which API gateway validates
The thing is I'm bit reluctant to implement SAML and oAuth thingy myself and looking for some ready made solution but couldn't find any, can someone please suggest of any library solving this problem, thanks in advance.
It feels like your approach is correct - it is the role of the Authorization Server (AS) to deal with SAML login integration for you. Only configuration changes should be needed, though of course you need to use an AS that supports SAML integration.
Your UIs and APIs will not need to know anything about SAML and will just use OAuth tokens. There should be zero code changes needed.
Most companies use an off the shelf AS - eg from a low cost cloud provider. My Federated Logins Blog Post summarises the process of integrating an IDP. The walkthrough uses AWS Cognito as the AS - and the IDP could be a SAML one.
I maintain a microservice that sounds like it could help you - https://github.com/enterprise-oss/osso
Osso handles SAML configuration against a handful of IDP providers, normalizes payloads, and makes user resources available to you in an oauth 2.0 authorization code grant flow.
Osso mainly acts as an authentication server though - we don't currently have a way for your API gateway to verify an access token is (still) valid, but that would be pretty trivial for us to add, we'd be happy to consider it.
I have a SpringBoot Micro-Service based backend API that uses Zuul as a gateway proxy between a JavaFX Desktop Application. Right now there is no security in place, but I am looking to secure the backend with Spring Security, however, every tutorial I seem to run across seems to be based on web-apps and I haven't seen anything for my particular use case. I don't know much about spring security but would like to know if I can accomplish my goals with it, and if so, what modules or examples should I be looking for.
Goals:
Provide a way for my API to know that requests are coming from the desktop app itself, I think the technical term for this is assigning the desktop app a client id and then having the Zuul Server validate that the client id is that off the desktop app before accepting the request. This should be the case for all requests
Only allow API traffic through the Zuul Proxy, all of the downstream requests to the micro-services behind the Zuul gateway should only be accepted if they are coming from the Zuul Server itself.
Allow requests for logging in and registering as a new user without any type of security other than the desktop client id discussed in 1.
When a user provides a successful username/password on login, they are returned a JWT which is then stored in the JavaFX application and used for all of the other requests to the backend.
Configure the token to expire after a specific time frame, say like 90 minutes and provide a method for automatically refreshing an expired token as long as the users account is still valid. For this, I don't want the user to have to re-login, I just want it to check behind the scenes to make sure their account is still valid and then issue a new token if needed.
Have user based roles so certain features, methods, endpoints, etc. are only accessible to users with the valid role. Within the GUI these features will be hidden or disabled, but I would still like a layer of security on the server side to protect against unwanted access in case someone was able to modify the app.
I am just writing down answers to each of your goals :
Passing the client Id in every request from desktop application doesnt make sense, instead you client Id and secret can be passed during authenticaiton call, Like we have in Oauth 2.0 framework. Rest https calls should be made from client, So to avoid tampering of request, You can also go for mutual SSL between your client application and Zuul API gateway, It assures that call is coming from Desktop client only.
Yes, Zuul api gateway should be single entry point to your application, Your internal microservices should not be exposed to public.
For user registeration, Client authentication can be achieved using client Id and secret
Correct, You can also create http only cookie at backend, which will include your jwt token only.
Token refresh can be achieved at zuul api gateway, if session is active, make call to refresh token endpoint to get new access token.
On server side, At zuul proxy you can validate the incoming bearer token expiry along with signature validation, with generic claims too. Now at microservices level spring security can be used for role based access control for particular methods.