I have 2 web applications:
Resource Server (#EnableResourceServer)
auth app (#EnableAuthorizationServer)
They are mapped to one database.
I would like to split database for 2: one for client app and the second one for tokens.
Question: How client app should be configured correctly with oauth?
My current flow:
Resource Server get request with token
spring security checks token in database
May be the best flow is to isolate auth app and database and flow should be something like this:
Resource Server get request token
and Resource Server makes a request to auth web app (OAuth Server) to verify token
auth app (OAuth Server) spring security checks token in database
?
Let me know if I misunderstand any point about oauth. Thanks.
If you want use the auth server for checking tokens you need a RemoteTokenServices (or the equivalent). If the server is a Spring Oauth sever (using #EnableAuthorizationServer) there should be a /check_token endpoint.
N.B. It might be a good idea to read the spec and get the terminology straight (your "client app" is a "resource server".
Related
i'm currently working on a OAuth2 Authorization Server using Spring Boot and the Spring Security OAuth2 Autoconfigure library.
Everything works so far except the fact that I need to authorize the client every time to access my protected resources. Is there any way to suppress the prompt or remember that i've already authorized the client?
Adding &prompt=none to the request params of my URL didn't work as expected.
I already tried to add a custom AuthorizationRequestResolver and adding prompt=none to every request, but that didn't work also.
Thank you in advance.
Usually after you are authorized by the authorization server, as a result you get an access token.
The resource server verifies against the access token to determine your client has the right to retrieve the requested resources.
With this background, one possible case is that:
Your client doesn't store the access token. So that everytime it hits the resource server, the resource server redirects the client to the authorization server to get the access token.
A solution of this is your client can store the access token. For the subsequent requests to the resources server, the access token has to be provided in an expected way. (like Aurthorization request header)
You may also find storing a refresh token is useful. Since there is no much background about your client app, cannot give a concrete recommendation for you.
If this is the case, you can log your outgoing request from the client to the resources server, you will see the access token missing in your request.
I am trying to set up authentication server for spring boot application. I have multiple microservices application. Let say hospitals, patients, reports applications. I have each of microservices service application to be authenticated before allowing user to access the resources.
Can I know how can I have common authentication logic as a separate application. let say authentication application. I am planning to us (spring security with Auth 2.0 and JWT token).
For example:
When user tries access hospital dashboard page, we will check the user is authenticated
First we need to check whether user is authentication if not I need
to redirect to login service in authentication application.
Once user is logged in, then when he try to access dashboard we will
check the token is valid. If valid then allow user to access the
dashboard service.
Now user try to access patient details which is there in patient.war as a separate project, as the user already logged in we need to valid token, then we need to allow access to resources API what he is trying to access. If token is invalid then we need to redirect to login page.
Question:
I have gone through some example they have authentication server and resource server as separate application. i.e #EnableAuthenticationServer and #EnableResourceServer. But I have noted this got deprecated in latest spring boot version if I am right. Please correct me if I am wrong.
How can I have authentication functionality as common war file and let the other resource server access it before allowing the user to access the reset service API?
Which is the right way to build a microservice application?
I need some experts help to understand the best approach we need to implement authentication and authorization in latest spring boot version.
This is a relatively older question but I'll answer since it may help others.
For any microservices-based architecture, the api gateway is an important aspect and it should be there.
All your microservices will be hiding behind the gateway and any calls made to the downstream services (hospitals, patients etc) will go through the gateway.
This gives you multiple advantages.
You can add login (authentication) functionality in the gateway
You can put rate limiter to avoid DOS attacks
A single point of entry for the outside world so your clients don't neet to know the URL of each microservice
Now, the way it works is:
The client sends username/password or client_id/client_secret to the /login endpoint which is inside the gateway (for example GatewayController)
Gateway sends credentials to an "Auth-Service" which authenticates the user from a db or anywhere and creates a JWT (Oauth token)
Gateway returns the jwt back to the client
Client calls the, let's say, /patients endpoint through gateway with the jwt as header "Authorization" parameter
Gateway -> Auth-Service (To validate the token)
If invalid, 403 forbidden is sent. Otherwise, request is forwarded to the downstream service (in this case Patients-Service)
Patients-Service sends the jwt token to Auth-Service to get permissions from inside the token since we know that the token has already been validated.
Once the permissions list is received, the Patients-Service matches them with the permissions mentioned on each api (for example PatientsController)
If any permission matches, the response is served. If not, 403 forbidden is served.
To make it more clear, Auth-Service is called once when the call is for login(authentication). Auth-Service is called twice for all other api calls(validate + permissions).
I am implementing oauth2 server using Springboot
I have four microservices
Sales (sales)
Inventory (inventory)
IAM service (Authorization Server, with Oauth2) (http://iam:8089)
Gateway (gateway on http://www.gateway.com)
All these services are behind the Spring clould gateway, and its deployed under K8S, And Gateway is exposed as external interface.
Now if I try to do authenticat user using oauth2 throught gateway like below.
Step 1 :
Http Request http://www.gateway.com/oauth/authorize
So in Response header I am getting like
Location: http://iam:8089/v1/oauth/login (But expectation is http://www.gateway.com/oauth/login)
and because of that browser
redirect me to http://iam:8089/oauth/login
Where Ideally I am expecting that also routed through gateway service something like
http://www.gateway.com/oauth/login
Can someone please help me to solve this.
Thanks
Alpesh
Sounds like a good setup in line with what we recommend at Curity in our IAM Primer Article, with the Authorization Server (AS) behind a reverse proxy or gateway.
In your case the AS listens at http://Iam:8089 but that is an internal URL. The AS also has a 'Base URL' that is used by internet clients, and this is the URL of the gateway, which is http://www.gateway.com in your example:
It will be returned to clients in OpenID Connect discovery requests
It will be returned to browsers in browser redirects during authentication
There should be somewhere in Spring OAuth2 Server where you set the Base URL, similar to that in the Curity Identity Server (see image below). The process should be to set this value and then verify that it is returned in a metadata request. You should then be configured correctly.
In Spring I expect the setting you need is in the fluent configuration somewhere - maybe one of the Configurer classes. I find it pretty hard to find what I'm looking for in Spring though.
I am not well experienced in Spring Security so my questions may sound a little weird.
My environment consists of 4 parts:
Keycloak authorization server (authorization server)
Spring resource server application (resource server)
2 OAuth2 client applications (clients)
I configured well everything, the OAuth2 and SSO work fine with all of the applications.
Besides the OAuth2 configuration, there is more to do. When my user uses the client application, he will provide his credentials on a form when trying to access the resource. But my model (for the resource) is more complex, and I have to do some background (housekeeping) tasks from time to time. These tasks are not done by the user(in the name of the user) but requested by the client application itself. My question is, how to access the resource server's endpoint from my clients in the name of the client application itself.
My first thought is that the client application should store a long-term JWT token and use this token during the calls. But I am not sure about it. I don't want to waste time on bad paths that's why I am asking in the first place.
The crucial and most doubtful parts for me:
How to get a long term JWT from Keycloak
How to automatically login a background call (via SSO and OAuth2)
How to store the credentials for the automatic login.
Thank you for your ideas or advice.
You should never have long term tokens, because that is a security risk.
If someone manages to get hold of a long term token, they then have long time to use it maliciously.
I can't guide you how to set this up in keycloak etc. But i would use the Client Credential Flow to authenticate the server, and get a token each time one of these "housekeeping jobs" needs to be made.
You can read more about the flow here Client Credential Flow
I have read and implemented my own Auth server following this tutorial from Spring. There are multiple SSO providers - Facebook, Github and a custom auth server. In this tutorial, the auth server contains the handling of other SSO providers.
I have a separate resource server that links to my auth server using the following properties:
security.oauth2.resource.userInfoUri=http://localhost:9000/user
I am able to get the token from my auth server using a cUrl command:
curl acme:acmesecret#localhost:9000/oauth/token -d grant_type=password -d username=user -d password=...
{"access_token":"aa49e025-c4fe-4892-86af-15af2e6b72a2","token_type":"bearer","refresh_token":"97a9f978-7aad-4af7-9329-78ff2ce9962d","expires_in":43199,"scope":"read write"}
But what I fail to understand is how can I use the other SSO providers to get such token as well from the auth server? The resource server should not care how did I get the token and whether I am authenticated using Facebook or my custom auth server. It should simply ask the auth server what is the Principal (logged user) and then decide which resources to show him, right?
I don't have any UI and this will be backed for a mobile application so I need to udnerstand how to handle the authentication using REST reqeusts.
If I understand your question correctly,
how can I use the other SSO providers to get such token as well from
the auth server?
This custom Auth server is abstracting out your interaction with FB or Github and issuing you it's own token. The token that your custom Auth server spitting out is not an FB or Github token, it's a token generated by your custom Auth server (After authenticating with FB/Github token).
Then why do we need FB/github?
How else your custom Auth server can identify a person, It sure can use user Id and Password; consider 'login with FB' as another nice option it gives to the user.
How to add other SSO providers like digitalocean in addition to FB and github?
Just do the same as we did for FB and Github (register a client id with digital ocean and then in auth server application, Add client Id and secret in the properties/yaml file etc)
The resource server should not care how did I get the token and
whether I am authenticated using Facebook or my custom auth server. It
should simply ask the auth server what is the Principal (logged user)
and then decide which resources to show him, right?
Yes, your understanding is correct.
Edit (To answer question asked in the comment)
But lets say I log in with Facebook through my Auth server. Where do I
find the token that I can use with the Resource server? Let's say I
have a RestClient and want to make a request to obtain some resource
belonging to a user which went through the Facebook auth process via
my auth server. Where do I find the token to use?
If that's a requirement, I think you can use this example instead; you may not need a custom auth server as such. Whole point of having custom auth server is abstracting out the interaction with FB or github.
Or
If you still want to go with custom auth server direction, then expose an endpoint from Auth server (which will get you the resources you need from FB) and then make use of that from your resource server.