What the configuration of spring-security-oauth2 authorizedGrantTypes means in practice? - spring

For example on the default jhipster UAA configuration we have:
clients.inMemory()
.withClient("web_app")
.scopes("openid")
.autoApprove(true)
.authorizedGrantTypes("implicit","refresh_token", "password",
"authorization_code")
.and()
.withClient(jHipsterProperties.getSecurity()
.getClientAuthorization().getClientId())
.secret(jHipsterProperties.getSecurity()
.getClientAuthorization().getClientSecret())
.scopes("web-app")
.autoApprove(true)
.authorizedGrantTypes("client_credentials");
So what does "authorizedGrantTypes" really means in practice? The first client "web_app" will have different types including refresh and so the second will be able to generate a token as client_credentials. What is the difference?
Another question, what is the purpose of the second client authentication which uses "client_credentials" ? Since this is disconnected from the real users stored. microservice to microservice communication? Looks bad if the configuration is deployed on spring cloud (client and secret hard coded configuration) to allow any external authentication via the gateway. How to prevent this?

OAuth 2.0 grant types are the different "ways" your client applications can obtain tokens.
There are a bunch of articles explaining it better, but here is a summary :
authorization_code is the "classic" OAuth 2.0 flow, where the user is asked for its consent through redirections. The client application is strongly authenticated because it has to send all its credentials (client_id+ client_secret + redirect_uri) before it can get a token.
implicit is almost the same as authorization_code, but for public clients (web apps or installed/mobile applications). The flow is almost the same from the user standpoint, but with weaker client authentication. The redirect_uri is the only security, as the client receives the access token through redirection + request parameters.
password is straight forward : the client application collects the user credentials, and sends both the user credentials (username+password) and its own credentials (client_id+client_secret) in exchange for a token. This flow mixes authorization with authentication, and should only be used when there is no other choice (i.e. your own installed/mobile application, where you don't want users to switch back and forth between native app and browser). You should never allow a third party to use this flow.
With all these flows, the user is asked for its permission, one way or another. The token given to the client allows it only to access that single user's data.
The client_credentials grant is different, as it does not involve a user. It is a drop in replacement for HTTP Basic.
Instead of sending a username (client_id) + password (client_secret) for every request, your client sends its credentials in exchange for a token.
It is used in server-to-server communications, where you want to know "which application is calling" by giving it distinct credentials, but you don't tie its authorization with a specific user.
Some examples :
a command line application (batch) or worker process consuming secured services. This kind of application probably processes a bunch of user data at once, and it cannot request each user's consent. The service called has to know "who" is calling in order to allow the client application to access anything.
a third party / external client of your API wants to know informations that are not linked to user data (for example : usage stats, quotas, billing...)
a third party / external client with special privileges who can access all your users' data
Note : In service to service communication, you should relay the token received from the outside instead of having each intermediate application request its own token.

Related

Server-2-server authorizaton in microservice architecture

It's clear for me about users authorization in microservice architecture (API Gateway for handling auth, SSO, authorization microservice and so on).
Now i'm thinking about authorization request between microservices.
And there is one question - which options i have in case when i have not got a user?
For example - analytics service, which requests data from billing and builds complex reports. There is no user, but do i need authorize request from analytics service to billing?
I know that there can be endless tokens, but i think its not good idea.
What another options for authorization request between services?
In OAuth2 specification there is such thing called machine-to-machine token. Which is different than password credentials flow which is refering to your user authorization.
To create a machine-to-machine token you should implement a flow called client credentials flow. In this flow basically all services have a specific client id and client secret and with those you are making a call to your central oauth-server to get a token. As it is also required to configure client details in the central service you will have the authorization in between client calls in terms of which client could call which others. There is also configurations for the time to live for each token.
If you already have the OAuth2 setup on your side it might be easy to introduce this new flow. But if you don't to implement such a thing on your side with your own setup could be tricky. Please check https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2#grant-type-client-credentials

What types of attacks do IdentityServer client secrets protect against?

I am trying to understand the purpose(s) of client secrets. Is it to prevent someone from creating a fake server that pretends to be my server? If not, what is it? And does it protect against anything else?
The client secret is used to identify the application that requires an access token in order to access a resource on behalf of the user. Only clients registered in the authentication service can request access. Not only will user authentication be necessary, the client application must also be legitimate. Otherwise someone could impersonate the client application.
This type of client authorization should only be used by confidential clients ([OAuth2 Client Types][2]).
confidential
Clients capable of maintaining the confidentiality of their
credentials (e.g., client implemented on a secure server with
restricted access to the client credentials), or capable of secure
client authentication using other means.
public
Clients incapable of maintaining the confidentiality of their
credentials (e.g., clients executing on the device used by the
resource owner, such as an installed native application or a web
browser-based application), and incapable of secure client
authentication via any other means.
When using flows with clients that cannot guarantee the confidentiality of this secret (i.e. implicit), the identity of the client cannot be verified. In those cases it can be verified by means of the redirection URI. As an additional measure, it should limit the exposure of refresh tokens.
Officially it is no longer recommended to use the implicit flow for security reasons, the recommendation for this type of clients is Authorization Code + PKCE extension. [See OBBA document][1]
For authorizing users within a browser-based application, the best current practice is to
o Use the OAuth 2.0 authorization code flow with the PKCE
extension
o Require the OAuth 2.0 state parameter
o Recommend exact matching of redirect URIs, and require the
hostname of the redirect URI match the hostname of the URL the app
was served from
o Do not return access tokens in the front channel
[1]: https://datatracker.ietf.org/doc/html/draft-parecki-oauth-browser-based-apps-02)
[2]: https://www.rfc-editor.org/rfc/rfc6749#section-2.1
Sometimes you have some ApiResources which called by Clients and there is no any user in the flow. for example fetch instagram's post using instagram's api. now instagram wants to control client behavior so client should be authorized for instagram befor any api call. in this situation you need define some secret for each client to identify them.
This an example of client's secret usage.

Spring oAuth2 with JWT using different authorization and resource servers

So I currently have this POC that I'm tinkering right now. I was thinking if it was possible that I can implement a Spring oAuth2 with JWT with a Authorization Server and a Resource Server both in different projects?
Flow goes like this User gets a token or passes through the Authorization Server and as long as he has the token and it's not expired he can make requests on the resource server.
I think that is the usual way to implement that. You have one authorization service providing tokens, either itself is backed by a database containing user information or maybe is asking another user service if the credentials are valid. The returned tokens can be used to make authorized request against the resource service(s).
Maybe take a look at the grant flow here.

How to architecture Microservice & OpenID connect?

We have three microservices: microA, microB & microC.
microA & microB are powering product 1.
microA & microC are powering product 2.
Obviously, we would need a security layer, in our case implementing an "OpenID Connect" provider fits well with the business needs. We add to the stack the OpenID provider.
The user/rights management is quite easy & natural: we associate the OpenId identifier of the user on each microservices to a subset of rights:
For example on the service microA, we store that the user OpenID XXX can do this and that. it's isolated on the microservice level. Respect the boundaries of our context. Fine.
When the user login with OpenID on product1, we grant an access token to the user + an Id token.
The situation becomes more complex when product1 expose an API that third-party use.
Now, let say that my user comes to the third-party webapp and is prompted to login & allow the third-party to get some rights on product1 API.
If I understand correctly OpenID connect, it's all about authentication over OAuth2, but how do we handle classic OAuth2 scope management then?
The best scenario I have found is:
make the whole OpenID connect to have the authentication info
and then make another full OAuth2 process to another Authorization server to ask the user to grant some scopes to the third party?
which means that on the third-party:
the user will be prompted to login on the OpenID Provider
then redirected and prompted to accept the scope requested
Is that correct? If yes, OAuth2 server flow is like 4 HTTP requests to the end user, so performing it twice is like executing eight requests to get the Authentication + Authorization flow done. Seems too massive.
I've already had this problem. What I would do in your case is:
Use this new OpenId microservice to authenticate the user and create the access-token. This access token can be a string with the permissions, user_id and the timestamp signed or you can store this info on a database.
Then, for every call (to product1 or product2):
I would force the client to send the access-token on the headers.
Then, when a microservice receives a call (lets say product1), I would send a signed request to the OpenId Microservice to ask if the user is allowed to perform that action.
That way, just the OpenId microservice knows how authentication works. So if in a couple of weeks you want to change how authentication works, you just have to change it on the OpenId microservice.
I dont really understand whats the problem with third-parties. They will get the token and they will be able to perform calls passingit on the Access-token header.

Spring oauth2 authorization flow - preapproval in app

we have a server to server communication that we wish to protect with oauth , but the authorization needs to be of a user. (cause the main server maintains a session and perform some validations of user permissions which are not spring roles checking ).
at first i thought of client_credencials but i needed to perform some mapping between the clientid and user. this kind of requires a hidden login on server to have the user session initialized.
also this is not the recommended flow (as written in the spring ClientCredentialsTokenEndpointFilter code)
so i think i want to try a different approach like authrization_code but i don't want any redirects here.i want something as simple as that.
user log in to our application (main server)
generate authorization request - like create API keys or something.
user is presented with authorization_code and state
user goes to the other server and put the code and state somewhere (don't care)
the other server use the code and state to be exchanged for token.
how can i achieve this ?
thanks
Shlomi
You can send a JWT from your server to the remote server that identifiers the user and the remote server can use that as a "grant" to obtain an access token from your server. This is called JWT Authorization Grant. The specification (work in progress) is here: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-jwt-bearer-12 but there are a number of implementations out there already. Below is an example JSON object that could be encoded to produce the JWT Claims Object for a JWT:
{
"iss":"https://jwt-idp.example.com",
"sub":"mailto:mike#example.com",
"aud":"https://jwt-rp.example.net",
"nbf":1300815780,
"exp":1300819380,
"http://claims.example.com/member":true
}
To present the JWT with the claims and header shown in the previous example as part of an access token request, for example, the client might make the following HTTPS request (with extra line breaks for display purposes only):
POST /token.oauth2 HTTP/1.1
Host: authz.example.net
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer
&assertion=eyJhbGciOiJFUzI1NiJ9.
eyJpc3Mi[...omitted for brevity...].
J9l-ZhwP[...omitted for brevity...]
Of course the implementations on both sides needs to support this grant type, but it should be be too hard to add this to an existing OAuth 2.0 implementation since it reuses large parts of other grant types.

Resources