When creating an external JWT provider in FusionAuth, there is need to set managed domains. When a new user is coming to my app, how can I know his domain ? Is there a possibility to set that all domains are accepted ? Wildcards and empty list does not work.
FusionAuth does not support a use case where you do not know ahead of time what email domain the user may be coming from. In order to validate the token signature from the 3rd party you will need to configure a public key, certificate or HMAC secret in FusionAuth such that we can validate the token.
A typical use case would be that you have a 3rd party that has employees that want to log into your application using their own IdP. In this case, let's say the company is Acme, Co, and each employee has an email domain of #acme.com. In this case FusionAuth needs the certificate or public key used by Acme, Co in order to verify the token sent to the Identity Provider Login API.
If you have a scenario where you do not know the origin of the incoming token, then FusionAuth also will not know how to verify the token signature.
I would need some additional context of your use case to see if it would be possible in FusionAuth.
Related
I know how OAuth2 and OpenID Connect works. But there is still some confusion bothering me.
We develop our own Auth Server, service API and mobile app. So, the client app is trusted and we use "password" grant type. The app user repository follows the same user database in auth server.
Our customers login to the app by username/password. The app then submits the user credential to the Auth Server token endpoint, which will return the (bearer) access token and ID token (JWT) to the client.
The ID token contains basic user information so that the app can greet user like "Welcome Tony Stark!".
The access token can be used to access API (e.g. update user profile).
OAuth by design is not a tool for authentication. Ref: https://www.scottbrady91.com/OAuth/OAuth-is-Not-Authentication
My questions are
1) Do we need to verify the signature of the ID token if the client only is only interested to get the user information? Also note that the ID token is coming from the token endpoint via https connection.
2) Let's forget about the ID token. Can we treat the user has passed the authentication check (i.e. login success) if the client obtains an access token from the Auth Server? This flow is very similar to simple password login without OAuth.
3) The client can access protected APIs with the access token. Without access token, the client can only invoke some public APIs. Is it equivalent to what can be done with and without login? It seems the access token can be treated as "login session cookie".
4) There is no 3rd party involvement in my case. Everything (client, auth server, service API) is developed and owned by the same organization. Does it still make sense to use OAuth?
Typically a mobile app is considered a public client. Unless you're limiting who has access to the mobile app, it can't be considered trusted as someone could mess with the app outside of your control even if you developed it.
Also, the resource credentials grant type is generally not a good idea.
One thing is that the OpenID Connect spec requires authorization code, id token, or a hybrid flow:
Authentication can follow one of three paths: the Authorization Code
Flow (response_type=code), the Implicit Flow (response_type=id_token
token or response_type=id_token), or the Hybrid Flow (using other
Response Type values defined in OAuth 2.0 Multiple Response Type
Encoding Practices [OAuth.Responses]).
Some other reasons:
Why the Resource Owner Password Credentials Grant Type is not Authentication nor Suitable for Modern Applications
The OpenID Connect RFC says you MUST verify the ID token:
When using the Implicit Flow, the contents of the ID Token MUST be validated in the same manner as for the Authorization Code Flow, as defined in Section 3.1.3.7, with the exception of the differences specified in this section.
Although, you may qualify for this exception from 3.1.3.7 if using TLS:
If the ID Token is received via direct communication between the Client and the Token Endpoint (which it is in this flow), the TLS server validation MAY be used to validate the issuer in place of checking the token signature. The Client MUST validate the signature of all other ID Tokens according to JWS [JWS] using the algorithm specified in the JWT alg Header Parameter. The Client MUST use the keys provided by the Issuer.
If you're able to trust the client, and the user/pass check you've implemented, then you should be able to trust that an access token has been granted to an authenticated identity according to the OAuth 2.0 spec.
The access token in OAuth 2.0 also contains scopes and should limit what can be done with that access token. A login without OAuth doesn't necessarily.
It's a good idea to use OAuth to protect the credentials of the resource owner. If you were to use the resource owner credentials grant type, this still provides some benefits as the user could enter the password only when the client doesn't have a valid access token, ie, the user can enter her password once for an access token and validate the user using that instead of entering the password again or storing it somewhere.
Even though this grant type requires direct client access to the
resource owner credentials, the resource owner credentials are used
for a single request and are exchanged for an access token. This
grant type can eliminate the need for the client to store the
resource owner credentials for future use, by exchanging the
credentials with a long-lived access token or refresh token.
OAuth 2.0 RFC6749
1) Do we need to verify the signature of the ID token if the client
only is only interested to get the user information? Also note that
the ID token is coming from the token endpoint via https connection.
YES.
2) Let's forget about the ID token. Can we treat the user has passed
the authentication check (i.e. login success) if the client obtains an
access token from the Auth Server? This flow is very similar to simple
password login without OAuth.
If I understand the premise. Yes..There is no requirement for using the ID Token.
3) The client can access protected APIs with the access token. Without
access token, the client can only invoke some public APIs. Is it
equivalent to what can be done with and without login? It seems the
access token can be treated as "login session cookie".
The access token is a access (like a key) that for the OAuth Client to use that was delegated permissions from the resource owner.
4) There is no 3rd party involvement in my case. Everything (client,
auth server, service API) is developed and owned by the same
organization. Does it still make sense to use OAuth?
Yes. OAuth and OpenID Connect are used by many, many organizations and is a test solution.
You should not try to re-invent the "wheel". Use known trusted libraries for Authentication, Authorization and cryptographic operations. OpenID Connect has some certified Implementations
I am using identity server 4, I followed the tutorial, so I have an api, mvc client, console client, and js client.
I saw this blog too, which is probably close to what I need:
https://medium.com/all-technology-feeds/testing-your-asp-net-core-webapi-secured-with-identityserver4-in-postman-97eee976aa16
what I need is an api, where clients can access data, but first, they need authenticate.
we also have the console client, which is also close to what I need.
The only issue with this examples is that in both cases client knows the secret. But in our case multiple clients should use the same api, and if they all have the same secret, they can log in on behalf of each other, but I don't want to have different secrets.
So what I think I could do is to create an api which takes username and password, and returns the token. But I am not sure if this is the right way to do things? This feels like a resource owner flow, which is not supposed to be used for client facing APIs if I am correct. But in that case, how should I go it?
thanks
It seems that there is some confusion. Allow me to give a short summary. First the terminology:
A user is a human that is using a registered client to access resources.
A client is a piece of software that requests tokens from IdentityServer - either for authenticating a user (requesting an identity token) or for accessing a resource (requesting an access token). A client must be first registered with IdentityServer before it can request tokens.
Resources are something you want to protect with IdentityServer - either identity data of your users, or APIs.
Client credentials: The simplest grant type and is used for server to server communication - tokens are always requested on behalf of a client, not a user.
Now about authentication. The client requests tokens at the IdentityServer endpoint. When you use a client in combination with the client credentials flow, then you'll need a clientid + secret. Where secret is really secret and should be known to the client only. You can't use the same secret here. Seems logical when compared to users, they don't share the same password either.
This is close to the resource owner flow, however a client cannot login as a user. For that you'll need another flow, like the hybrid flow. In that case the client logs in on behalf of the user. The difference is the presence of the "sub" claim (the id of the user) in the token.
The client in this case is your app: console or mvc. The first only supports client credentials where the secret is mandatory, the second supports a hybrid flow, where secret may be omitted:
In certain situations, clients need to authenticate with
identityserver, e.g.
confidential applications (aka clients) requesting tokens at the token endpoint
APIs validating reference tokens at the introspection endpoint
The Api is your resource, that you want to protect. The Api never authenticates a user or client. This is done by IdentityServer. It only verifies the token (using the IdentityServer4.AccessTokenValidation package). For that it has its own secret that should only be known to the Api.
In order to grant the client access to the resource you'll need to add the scope to the client in the configuration of IdentityServer. The client is then allowed, not required, to request a token that grants access to the resource.
Again, the Api has nothing to do with authentication. It is also not bound to one client. Multiple clients can access the resource. All you have to do is add the scope to each client that should have access to the resource.
So there is really nothing against it that clients and resources know their secret. You don't have to change anything. All you have to do is choose the appropriate flow.
My client asked me to develop a web api and use SAML as authentication.
I came across with the image below from this site, that shows the authentication flow.
However I don't know how to use the token that is generated after the authentication.
Do I need to store it as any other session variable?
Do I have to renew the token after a certain time or it lasts during all the session?
Note: The authorization server / idP is maintained by other party.
Since you develop the web API yourself, there's no need to refresh the token.
You're API needs to be added as relying party to the IdP. After that you can redirect to the IdP and initiate authentication. The token you get back contains several attributes (also configurable on the IdP) like unique user-id (uid), e-mail, name, country, etc...
In most cases this token is signed using a public/private key. Your API server needs to verify the signature, the issuer (the IdP), the audience (your API) of the token and consume the attributes. When everything is OK, you'll need to provision a local user account, link the external uid and create a local authentication cookie (or generate a OAuth2 token if your API uses OAUth2 or OpenIdConnect) for the locally provisioned user account.
Since this is a complex process, depending on the language/framework you're using, you might want to look into existing implementations.
Suppose we have some RESTful API whose resources we want to expose. End users will work with this API through client applications like mobile apps and Javascript based clients that run on web browsers.
With OAuth 2.0 this RESTful API will lie on the Resource Server and we will have one Authorization Server on which the client applications are registered. The users will then be registered at the authorization server and will be able to grant permission to those applications access resources on their behalf or not.
So when the user access one client application he will be redirected to the Authorization Server and be prompted to grant permissions to said client app. After that an access token is issued and the client is able to make requests to the Resource Server.
All of this is quite clear to me. There's just one missing piece: the protection of each resource might be user-dependent. To be more precise it might be claims-dependent. What I mean by that is we can have the following situation:
The resource http://resourceserver.com/api/first-resource should only be accessible to users with claim "ExampleClaim" with value 123.
The resource http://resourceserver.com/api/second-resource should only be accessible to users with claim "AnotherClaim" with value 123.
The resource http://resourceserver.com/api/third-resource should be accessible to any users.
When I first heard of OAuth was dealing with ASP.NET WebAPI and I dealt with that in the following way: when the request was sent with the Authorization: Bearer [token] header, on server side the thread principal was set and I thought that this meant the user was authenticated with the API. So I used [Authorize] attributes in order to verify if the user could access the resource.
After studying OAuth more deeply I saw this was a terrible misuse of the protocol. As I've learned, OAuth authorizes applications and not users. When the request is made with the Authorization header, as I've learned, the access token shouldn't contain information about the user, just about the application being allowed to make the request.
Considering that, sending the Authorization header with the request doesn't identify the user and does don't say if the user can or cannot access said resource.
In that case, how does one perform this kind of authorization? I mean, not authorization of the client app performing the request, but the authorization of the user accessing the resource based on his claims? I believe this is where OpenID Connect and it's ID tokens come in, but I'm unsure. How does one manage this?
An access token does not contain a user's claims, but it contains the subject of the user who has granted permissions to the client application. "Subject" is a technical term and it means a unique identifier. Simply saying, "subject" is a user ID in your database.
At a protected resource endpoint, you will do:
Extract an access token from the request. (RFC 6750)
Get detailed information about the access token from the authorization server. (RFC 7662)
Validate the access token. The validation includes (a) whether the access token has expired or not, and (b) whether the access token covers scopes (permissions) that are required by the protected resource endpoint.
The steps above from 1 to 3 are an access control against client applications. OAuth 2.0 (RFC 6749) is for this. See "Protected Resource" by Authlete (by me) for details about these steps.
After the steps above, then you will do:
Extract the subject from the access token. Again, "subject" is a unique identifier of the user.
Retrieve claims of the user from your database.
Validate the claims as you like.
The steps above from 4 to 6 are an access control against users. OAuth 2.0 is NOT for this.
The primary purpose of OpenID Connect is to get an ID token in a verifiable manner. You can confirm that an ID token has been issued by the right party by verifying the signature attached to the ID token. See JSON Web Signature (JWS) (RFC 7515) for details about signature.
An ID token itself is not a technology to protect Web APIs. But you may be able to use it for that purpose if you use at_hash claim in an ID token properly (see "3.1.3.6. ID Token" in OpenID Connect Core 1.0). However, at a protected resource endpoint, it will be much easier to get claims directly from your database than to parse an ID token.
**[ Additional answer #1 for the comment ]**
In your use case, you don't need ID tokens. It's because an access token already contains information about the subject of the user. In normal cases, the information is equivalent to the value of sub claim in an ID token.
Therefore, you don't need an ID token to get the subject of the user. See the description of step 4, and you can find "extract the subject from the access token."
**[ Additional answer #2 for the comment ]**
So is there anything wrong in extracting the subject from the access token like that and verify the claims? Or this is the right way of doing things?
There is nothing wrong. For example, suppose you define a Web API, https://api.example.com/profile, which returns the profile information of a user. In normal cases, such an API would accept an access token and then extract the subject from the access token to determine which user to refer to. On the other hand, if the API did not extract the subject from the access token, it would have to require "subject" as a request parameter to determine which user to refer to (or require an ID token that contains "sub" claim). Even in such a case, the API must check whether the subject specified by the request parameter and the subject associated with the access token are identical because otherwise, it would become a security issue.
Checking claims after extracting the subject is also a normal step. For example, you may want to restrict the functionalities of your service based on the plan that the user has paid for (Free plan, Lite plan, Enterprise plan, or whatever). In this case, you would have to refer to plan claim. Of course, checking such a claim can be done only after extracting the subject from the access token.
Therefore, (1) extracting the subject from an access token and then (2) verifying the claims of the user are normal and even typical steps in implementations of protected resource endpoints.
You are right, OAuth is NOT an authentication protocol but rather a delegation protocol.
OpenID Connect adds two notable identity constructs to OAuth 2.0's token issuance model.
an Identity Token - the delivery of which from one party to another
can enable a Federated Identity SSO user experience
a standardized identity attribute API - at which a client can
retrieve desired identity attributes for a given user.
The ID TOken can be presented to the userinfo_endpoint to obtain the information and provides level of assurance that the user has been authenticated by the OpenID Provider.
BTW: The "sub" ie only unique within the context of the Authorization Server. It is recommended IF you store the sub you also store something like iss-sub. The thoughts are tsmith at Google may not be tsmith at Twitter
The model for our product is like this:
Api backend (headless)
I already have oauth set up and ready to use with a resource owner credentials grant. Anyone who wants to use our api can do so using either an API key or their username/password. Of course they also need their client ID and secret.
SPA frontend that accesses the Api
I have built an SPA that will uses the api to provide a portal GUI for our clients. Given that this client-side app is owned and administrated by us (so it's a trusted app) how can I safely authenticate users using only username/password with oauth?
Originally it was using a JWT auth system that only required username/pass but now that we've implemented oauth I'd like to consolidate. It's unreasonable to make every user need to also have their client id and secret on hand to login, but I want users to have full access to the api from the GUI.
I've looking at using CSRF tokens but how would that work with my app when nothing is generated server-side?
I'm not sure how to proceed.
EDIT: very similar to the problem here.
I have decided to use the solution described here.
And here is a snippet of my implementation
The TL;DR version is
Create a proxy between the app and the api
Store the client ID and secret in the proxy
App logs in using password grant type -- proxy intercepts login request and inserts client id and secret
On login response proxy returns access token as an encrypted cookie
Client stores cookie and sends with api requests (to proxy)
Proxy decrypts cookie and inserts access token into Authorization header before forwarding to api endpoint
For me this has several advantages over implementing something custom on the api itself:
No need for custom grant on oauth server
ID/secret is hidden from app securely and can still use password grant
oauth server can identify client (no need for separate client ids for each user)
You should not use the resource owner credential grant from a JavaScript application. The fact that you own and administer the application does not make it a trusted application.
A trusted client is an application that can keep a secret. SPAs or any JavaScript app cannot keep a secret.
You should use the implicit grant for non-trusted clients.