I'm trying to implement Two Factor Authentication (2FA) in a Web API 2 solution using OAuth 2 and Bearer Token with the help of OWIN. I know 2FA with Bearer Token is not a standard workflow but has anybody successfully done this?
Basically, I have two scenarios I need to cater for:
User credentials are correct and no 2FA is required so return full authorized Token. This I have done and works correctly and works with methods in Web API controller that has the [Authorize] attribute on.
User credentials are correct but 2FA is required so I want to return a valid Token that does not give them full access, so methods in Web API controller with [Authorize] attribute do not allow access.
Once the security code has been successfully entered I want to then generate a new full-blown bearer token as in scenario 1 above and return that, giving full authorized access.
I'm using Identity 2 to create the secure code and email the code, which works fine but the area I'm struggling with is in the overridden GrantResourceOwnerCredentials method to cater for the two scenarios above. Any information or code examples would be appreciated.
Related
I’d like to ask a little help from my friends.
It is essentially about openId/oauth flows, I am a little confused about flow types.
Currently I am working on a modernization project and I need to establish a new authentication / authorization flow for legacy and new components.
My doubts are regarding to what implementation should I do and which I should use from authorization server, ie:
Flow 1 and Flow 3
User will supply login credentials to a Web MVC application and it should authenticate in cognito, return a token. (1a / 1b) (3a / 3b)
In subsequents interactions with BFF 1 / 2 and other microservices, I will pass the same token, right? What is the right way to validate this token in the backend? (4)
Flow 2
Some external users are able to access systems using APIs using basic credentials (login/password).
In the modernization scenario, what should be indicated to them? Client Id / Client Secret ? Or is it ok to use login / password to get a token?
Very thanks for help
None of those flows are OAuth2 and strictly speaking, nothing about your diagrams relates to OpenID.
In subsequents interactions with BFF 1 / 2 and other microservices, I
will pass the same token, right?
Yes, you can use the access token or id token to authorize future requests.
What is the right way to validate this token in the backend?
The tokens generated by cognito are all asymmetrically signed JWTs. You can verify the signature using any JOSE/JWT library. https://jwt.io/ has a good list at the bottom of the page. Cognito doesn't currently support token introspection so your resources are not able to pass the token to cognito for verification as your diagram shows.
Some external users are able to access systems using APIs using basic
credentials (login/password). In the modernization scenario, what
should be indicated to them? Client Id / Client Secret ? Or is it ok
to use login / password to get a token?
This should be a client credential grant. However, Cognito's implementation is pretty sloppy and doesn't support rotating secrets. Additionally if you are relying on ID tokens then those are not supported by this grant type. Password grant is technically supported by cognito but would allow any user to authenticate with username and password through the client. The best option might be to create a custom auth challenge and handle your authentication through that.
I am confused about the use of OAuth 2.0 as an Authorization method and OpenID Connect as an Authentication method.
Based on my knowledge OAuth 2.0 is only an Authorization method. In other words, this is the process to request an ACCESS_TOKEN and RECEIVE this ACCESS_TOKEN, like depicted in the image below in yellow ellipse: (simplified)
Before an OAuth 2.0 Client retrieves an ACCESS_TOKEN from an Authorization Server this Server should verify if the User allows it and this is an Authentication Process that OAuth 2.0 does not care about.
When OpenID Connect is included in the mix it allows for an Authentication Method as well, but in my knowledge OpenID Connect just adds a "Claim" in the JWT Token that holds information about user that is using the service, like: email, name and others.
My questions are:
Why not ignore OpenID Connect and just add more "claims" in OAuth
2.0 to get information about users?
Is my description of the flows correct?
OpenID Connect does not merely "add a claim in JWT Token" but:
it introduces a completely new token (id_token) with radically different
semantics than the OAuth 2.0 access_token and a standardized format that is understood by the Client as opposed to the access_token which is opaque to the Client
it "twists" the role of the Client, now becoming the "audience" (or: intended recipient) of a token (i.e. the id_token) whilst the audience of the access_token is still a remote entity (aka. Resource Server) and the Client is only the "presenter" of the latter
The 2nd item is the primary source of confusion between OAuth 2.0 and OpenID Connect.
I don't know if your method will work or not but you're totally free to roll your own authentication. After all, that's what Facebook, GitHub and many others did by customizing oauth2. There ended up being so many oauth2 "authentication" methods that it was never plug and play if you wanted to change your provider. I believe that's why OpenID connect was introduced--a common way of connecting and reasoning about authentication while building on the established oauth2 pattern for authorization. Use OpenID connect or don't...but if you don't you'll be reinventing the wheel.
#sdoxee answers explains thing correctly. But I am adding bit more information for OP's understanding.
These days many identity providers (eg:- Azure AD) issue JWT based access tokens. These JWT access tokens do contain claims about end user as well as JWT related validation details (eg:- Token expiration). Here is the link for Azure AD OAuth 2 success response which highlights access token to be a JWT. Also, see JWT claims to see how they explain the claims. Samples are given below,
family_name : User’s last name or surname. The application can display this value.
given_name : User’s first name. The application can display this value.
One could think of building authentication on claims present in access token, but this is not sticking with protocol. And mostly claims and user information will be implementer specific. Also, by protocol definition, these two tokens (id and access) have two different audiences.
ID token is for client, for validation and for authentication.
Access token is for OAuth 2 protected endpoint.
Again, as #sdoxee highlight, use the correct protocol at correct place. Having claims in access token does not necessarily mean you should use them for authentication.
Whats the best way to programmatically authenticate user using OAuth 2.0 Authentication Code Grant ?
Wondering if there is a way to combine step A and B as stated on the spec - https://www.rfc-editor.org/rfc/rfc6749#section-4.1, i.e pass user ID and password as part of authorize call ? Something like,
/authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb&user_id=john.doe#mail&password=xxxx
I believe one way is to submit() the form returned by the Authorization server with user id and password. Taking this route would create a dependency on the form and any changes to it given it is not a public API.
The Authorization Code grant is designed to be used with a full browser i.e. should not be used to authenticate the user programmatically. In fact using it programmatically would defeat the purpose of OAuth 2.0 to not divulge the user's credentials to the Client.
Grants like Client Credentials and Resource Owner Password Credentials have been designed to be used with non-browser Clients.
Alternatively you could create an access_token and refresh_token for your Client in a browser using the Authorization Code grant, then pass the tokens to your non-browser Client so that it can use the refresh_token on its own to obtain a new access token when the old one expires.
The OAuth2 spec defines a Client Credential grant for machine-to-machine authorization, where a user isn't involved. Identity is confirmed via a client secret. This isn't appropriate for a native client, such as a mobile application, because stored client secrets can't be guaranteed.
Mobile apps can make use of the OAuth Code Authorization grant plus Proof Key for Code Exchange (PKCE), which allows a dynamically generated secret. This is great if you need user authorization/authentication.
However, what if you just need to protect your API's resources so that only your mobile app can use it, but you don't track users? That is, I'd like to get an access token for my application, instead of for a user.
It seems like Code Authorization + PKCE would work great, if only both the login and consent screens could be disabled. Just return the auth code. I was hoping to find a way to do this in IdentityServer3, but haven't.
Is there a configuration or flow that allows this? Or am I making a security mistake?
EDIT
It further seems to me that using PKCE should allow for a flow with two backchannel calls, one to the authorize endpoint, the other to the token endpoint. Essentially, Code Authorization without the browser redirection. I know such a flow isn't in the spec, but am I right? Regardless, the question remains, how to authorize a mobile app using its own account, not a user's?
I'm about to start working on application with rest API and I want to use apigility. There is one problem unfortunately with this idea. I cannot find reliable source of information how to allow for authentication by oAuth for regular users.
I need to provide access for angular app and native mobile one (possibly in future for third-party web apps). All resources that I have found are about granting access to api for specific client application, not for specific users that use this applications. I don't want to implement two different authentication methods, so if there is a way to resolve this issue with apigility it would be great.
Do you have any suggestions how to approach this? I know that I can generate client id and secret for all registered users but this seams a little crappy solution and I have database schema already in place for storing user info.
What you're likely looking for is the "password" grant type. In this scenario, you will have a way of registering users and their passwords, and then a "login" screen of sorts. This login screen will send the following information:
username
password
client_id -- this will be the OAuth2 client ID (not the user ID!) for the application
"grant_type": "password"
Note that you are NOT providing the client_secret in this scenario! In the case of a user credential scenario, the user's credentials are validated, and then the server verifies that the client_id supports this grant type.
If the user provides successful credentials, then the OAuth2 endpoint will return a token, a TTL, and a refresh_token (which, if you send it before the TTL expires, will give you a new set of tokens).
From here, you will then send the token in the Authorization header: "Authorization: Bearer ". Apigility will then pick this up on each request and validate the token.
The validation returns also the username as part of the identity. This means that you can query the ZF\Mvc\Identity to retrieve the user in order to perform user-specific ACL assertions later!
Poke me on the mailing list (http://bit.ly/apigility-users) if you need some more direction.