Resource Owner Credentials Flow with JavaScript and IdentityServer - Not Allowed? - asp.net-web-api

I have a JS website that tries to obtain an access token by passing the user name and password. I also maintain the auth server, so I consider the JS client as trusted. I am able to do this with ASP.net 4.5.x. but when I try to do the same to IdentityServer, I get invalid_client.
I'm now trying out ASP.net 5, and I believe the old OWIN middleware for acting as the identity provider is no longer going to be supported, and they are advocating IdentityServer for when we want to be the identity provider.
POST /connect/token HTTP/1.1
Host: localhost:59766
Content-Type: application/x-www-form-urlencoded
username=admin&password=pw&grant_type=password
I think the IdentityServer requires client information first, but that would mean I would have to expose client_secret on a web page (or native mobile app), which I believe is not allowed, per OAuth specs.
How do we turn off client requirement with IdentityServer?
On IdentityServer's github, I only see C# code that gathers client credentials plus user name and password to obtain an access token for resource owner credentials flow here. What is the equivalent raw HTTP request?
I personally don't care if another app were to try to impersonate my client. It's really the user's credentials that would allow access to anything anyway.

In IdentityServer3, client authentication is mandatory: a token request cannot be validated if the client credentials are missing from the request, no matter which grant type you're using (authorization code, refresh token, resource owner password).
Of course, this is not really specs-compliant since client authentication is not needed for public applications like JS apps, but I guess this requirement is here to encourage you to use the implicit flow instead (https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2)
If you really want to use ROPC with IdentityServer, you can flow the client credentials with the other OAuth2 parameters:
POST /connect/token HTTP/1.1
Host: localhost:59766
Content-Type: application/x-www-form-urlencoded
client_id=id&client_secret=not_secret_at_all&username=admin&password=pw&grant_type=password&scope=read+write

Related

Should OAuth2 resource servers use Basic or Bearer token auth when communicating with the authorization server?

Given separate spring-security-oauth2 authorization and resource servers:
I expected the authorization server's /oauth/check_token endpoint to accept a Bearer token from a resource server in the Authorization header but it only accepts Basic auth. Note: I'm referring to the request auth token, not the token to be checked.
I think OAuth2AuthenticationProcessingFilter is responsible for extracting and validating Authorization: Bearer ..., but based on the javadoc it appears to be used only by resource servers to validate requests from users or other clients.
Should resource servers always provide Basic auth when communicating with the authorization server? What's the best practice? If Bearer tokens are acceptable, does the authorization server need to be configured as a resource server via #EnableResourceServer in order to get this functionality?
Note from the Javadoc for CheckTokenEndpoint:
Controller which decodes access tokens for clients who are not able to do so (or where opaque token values are used).
Since the client authenticates with the authorization server with Basic auth to grant access, it makes sense for the /oauth/check_token endpoint to require Basic auth as well.
Usually, the tokens the resource server receives are self-encoding (or backed by a token store), so it doesn't need to check the token by directly communicating with the authorization server anyway. Communication between the resource server and authorization server is not necessary.
If it does need to interact with the authorization server, it might be to obtain its public key if you're using JWTs. But there would be no real use in securing this endpoint, since it's a public key for a reason. Again, this would happen when the resource server starts up, and certainly not for every token it receives.

Which information gets sent in each API request using OIDC

I'm writing an API back-end that I want to use OpenID Connect (OIDC) to secure. I've been reading the documentation but I'm still a bit confused what process applies to each and every API request. The Open ID Connect code flow appears to be:
Which I'm fine with, as a one-time process. My back-end API sees an authorization code in the HTTP headers, and sends a request to the authorization server to get the id token. Assuming this validates OK, the data requested is returned in the API response.
But assuming the same user will then be making lots of requests to this API, what happens in subsequent requests? Is there some sort of session created in this mechanism? Do I continue to receive the same authorization code? Do I have to keep sending these back channel requests to the authorization server?
Or should I even output the JWT id token as a cookie? In this way I get the self contained id token coming back in future requests, with no need of a server side session, or further round trips.
I've been reading the documentation but I'm still a bit confused what
process applies to each and every API request
It is not the API that should follow OpenID connect protocol. It's the client that should do it.
My back-end API sees an authorization code in the HTTP headers, and
sends a request to the authorization server to get the id token.
Assuming this validates OK, the data requested is returned in the API
response.
Authorization code must be used by client application and not by the API endpoint. Also, authorization code must never be exposed to other entities.
You should use id token sent with OpenID Connect to authenticate the end user from your client application. To access API, you should use access tokens.
What to do in API endpoint ?
I think this is where you struggle. Your client application should send a valid access token to get access to API endpoint. From API endpoint, you can use OAuth 2.0 introspection endpoint to validate the tokens.
RFC7662 - OAuth 2.0 Token Introspection
This specification defines a protocol that allows authorized
protected resources to query the authorization server to determine
the set of metadata for a given token that was presented to them by
an OAuth 2.0 client.
Note that, OpenID Connect is built on top of OAuth 2.0. This means you can use anything defined in OAuth 2.0, including introspection endpoint. Use this endpoint to verify the access token validity.
What if you want end user details ?
OpenID Connect defines a user info endpoint
User info endpoint
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User. To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication. These Claims are normally represented by a JSON object that contains a collection of name and value pairs for the Claims.
Here also, you use access tokens to get user information from this endpoint. The response will let you know the end user to which this token was issued.
Depending on your specific API requirement, you can do a token introspection or obtain user information from user info endpoint. Once that is done you may go ahead and authenticate a session. You might use both endpoints if you need all available information.
Alternatively(instead of sessions) your API can maintain an access token cache. This will remove the need to validate tokens in each an every API call. But be aware that tokens have expiration time. You must consider about token expiration if you are choosing this solution.
p.s - Client vs Resource server
In OpenID Connect and OAuth 2.0 terms, a client could be a simple web page, desktop application or could be even server hosted application.
client
An application making protected resource requests on behalf of the
resource owner and with its authorization. The term "client" does
not imply any particular implementation characteristics (e.g.,
whether the application executes on a server, a desktop, or other
devices).
Obtaining tokens and using them is the duty of the client application.
On the other hand, resource server contains protected resources,
resource server
The server hosting the protected resources, capable of accepting
and responding to protected resource requests using access tokens.
Resource server exchange it's resources to access tokens. If we match the same scenario to basic authentication, access tokens replaces username/password sent with authentication headers.
Typically you'd secure a (pure) API with OAuth 2.0, not OpenID Connect. The Client accessing your API should obtain an OAuth 2.0 access token and in order to do that it may choose to use OpenID Connect to obtain that token. That is all independent of the API, which will only see the access token. The API (or Resource Server in OAuth 2.0 terminology) is not depicted in your diagram.

Authenticating an API request with a Token

Suppose I make an API request to the following URL:
https://myapi.com/data
This is an API I built and have full control over.
I would like to limit access to this API to only the apps I authorize.
I see many services will provide you with an API key which you can append to your URL to give you access.
Suppose I have:
https://myapi.com/data?key=a6reallly7long2string9of0numbers2and4letters
Then on the backend I have something like:
class REST {
public $ACCESS_TOKEN = 'a6reallly7long2string9of0numbers2and4letters',
public function Auth($token){
if($token===$this->ACCESS_TOKEN) return true;
return false;
}
}
If the values match, I allow access.
But all someone would have to do is look at the request the app is making on the client side and they have the token.
Even if I encrypt the token or use one-way hashing, they'll still have the value that decrypts to the correct result.
How does one approach good authentication via URL token for an API?
I would like to limit access to this API to only the apps I authorize.
What are you looking for is "access authorization". Indeed, an access token seems to be a good way, but there are some aspects missing
** Authorization header **
By default the token should be sent as an HTTP header (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) not in the url
Commonly used Authorization headers types are Basic (for basic authentication) and Bearer (for OAuth authentication and authorization)
The token should not be a hardcoded constant. It should be created/generated based on the application (and optionally user) authentication. And still better if the token is temporary
Now you can ask - how can an application keep its credentials secret? Each application can have their own server services (end user should.not access application credentials) or pure web application should be comtrolled by the CORS headers
Just search for OAuth 2.0 protocol and JWT token (jwt should be self-contained and signed).
IMHO the URL token may be an option when there is no other alternative, as URL is often cached, resent, logged,...
** API Manager **
If you have resources (server) to do so, you can deploy an API manager (there are open source, commercial or cloud options, just search for some). API manager will handle the application enrollment, authorization and enforcement.

Client secret + refreshing the access token in spring oauth2

I am using spring boot for backend and Android device for frontend of my system.
Right now I am facing the challenge to use Spring-OAuth2 to secure my resource server.
I have some questions, which I want to discuss with you:
My knowledge + this tutorial are saying that I should use the OAuth2.0 "password" grant type for my mobile app to obtain an access token. The official spring tutorial for security gives an example how to obtain the access token using password grant type:
$ curl client:secret#localhost:8080/oauth/token -d grant_type=password -d username=user -d password=pwd
And here comes my first question: Is there any possibility to obtain access token using the password grant type without sending the "client secret" ?
Since the client secret could be "reverse engineered" by decompiling the client app. The obtaining access token without secret should be somehow possible, because Facebook SDK for Android also does not need the client_secret in the mobile app.
I think here I have a little trouble understanding why the clientID + clientSecret needs to be included in the request above, because, since there are already username + password included, it should be possible to generate the access token, so does this brings a next level of security ? and does it implies the following (example): I am logged in as Filip in my Android client and I am sending the access token A with each request to the server. Then I log in as Filip into web client and I try to access the resource server from web client using the access token A, which is not possible because access token A was issued only for Android client ?
The next question is how can I refresh the obtained access token ?
I was trying to do so using the command below, but I got "Full authentication is required to access this resource." After I got the new refreshed token, can I use the refresh token to refresh my new access token again ?
curl -v --data "grant_type=refresh_token&client_id=acme&client_secret=acmesecret&refresh_token=REFRESH_TOKEN" http://localhost:9999/uaa/oauth/token
Thank you
The OAuth 2.0 spec allows for so-called public clients i.e. clients that don't authenticate themselves. So it is possible to use the Resource Owner Password Credentials grant with a public client, i.e. one that does not need to send a client secret. It does mean that the Authorization Server cannot assume anything about the client since a client_id is not a secret and there's no way to prevent a malicious client using this grant type or clients from impersonating each other. So using it in this way comes at the cost of reduced security although one may argue that in your case there's no way to use confidential clients anyhow, so there's no difference.
In general the Resource Owner Password Credentials grant is an anti-pattern for OAuth and only meant for migration purposes because it defeats most of the goals of OAuth in itself.
Access tokens are issued on a per-client basis.
You refresh token request seems OK but the Authorization Server may require basic authentication instead of providing the client_id/client_secret as post parameters, considering that you did the same for the original access token request.

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