Why do we need first contact the Oath Auth endpoint to get an auth code, and then once we have received the auth code we need to contact the Oauth Auth endpoint again to get the access token so that we can call a webservice?
Why not just return the access token in the first step, after the user has signed in successfully?
Also, how does the webservice (API) then verify that the access token is legit?
Why do we need first contact the Oath Auth endpoint to get an auth code, and then once we have received the auth code we need to contact the Oauth Auth endpoint again to get the access token so that we can call a webservice?
So the web service (or Relying Party) never sees the user's credentials.
And because of how this flow works, the user also cannot see the application's credentials.
User also can't get the access token to use it themselves, though that actually would not matter that much.. Implicit Grant Flow actually does what you want, allowing you to get an access token directly from the authorization endpoint. But that is mainly for Single Page Apps, for which that is the easiest option.
Authorization Code Grant flow allows the app to use a stronger authentication via a client secret or certificate.
This is called an OAuth dance by the way :)
Why not just return the access token in the first step, after the user has signed in successfully?
See my mention above about Implicit Grant flow.
Also, how does the webservice (API) then verify that the access token is legit?
By checking the digital signature. Azure AD (and B2C) publish public keys for the key pairs they use for signing at a well known endpoint.
The authentication pieces in an app must check the JWT signature is valid by the defined public key.
Related
I want to get access token with a certificate.
I know values of these client_id, grant_type, scope from my application.
But where can I find values of assertion and client_assertion.
Do I need to get more tokens, I'm completely lost here.
Can anyone guide me with working example?
This is a sample. It can be summarized as:
go to this url to get auth code:
https://login.microsoftonline.com/tenant_id/oauth2/v2.0/authorize?
client_id=aad_client_id
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&scope=api://aad_client_id_which_exposed_api/permission_name
&state=12345
2.use auth code to generate access token by auth code flow.
3. use access token to generate another access token by obo flow.
On behalf flow is used when an API want to call another API. So at first you need to have a web api which is protected by AAD, so that it can receive an access token A. After having this token A, on behalf flow can generate a new token B by A, so A is the value for parameter assertion. Then using client id + client secret and follow this section to generate access token by obo flow. And this is what I do in the screenshot.
Azure AD also also us to use certificate rather than client secret to complete the authorization. So we can also follow this section to do it. As you can see, missing client_secret but appear client_assertion_type client_assertion.
Then the only issue left is how to get the token A. Just like what I say, token A is used for visiting API which is protected by AAD, so you need to expose an API and give the api permission, then update your project to authorize the scope right? Then this tutorial demonstrate the whole progress. Finished all the steps, then you may need to sign in with your onmicrosoft.com account first, then you can get a code from the url in the browser, then use that code to generate an access token, this token should had scope like api://aad_client_id/xxx, and this is token A.
You may also refer to this tutorial, this can help you understand obo flow.
I'm using cognito to authenticate to node-js using amazon-cognito-identity-js I logged in and it returns me an access_token, id_token and refresh_token but none of them work when I'm using the open id scope with authorization code grant.
I don't know if I need to call another service or do another process to get access at the gateway
but when I generate a token using client_credentials flow the api gateway works
If I understood correctly, the scopes you are setting are OAuth 2.0 scopes and require using the OAuth 2.0 endpoints (e.g. the hosted UI, or an external IdP federation). Your code seems to be using the non OAuth 2.0 flow (e.g. I assume InitiateAuth with SRP). If you decode the JWT I believe you will see it has only the aws.cognito.signin.user.admin scope.
For using custom scopes you will need to
send the access token (not the id token)
use token you got from the token endpoint (e.g. using the hosted UI or federation) - they will contain the scopes you set in the screenshot
For using the open_id scope, same as above but send the id token, not the access token, and remove the custom OAuth scopes in API Gateway (if you put them it will expect an access token)
p.s. custom scopes work great with the client credentials flow, but less with the authorization code flow if it doesn't have a client secret.
Lastly I recommend you take a look at AWS Amplify as it will handle a lot of that for you behind the scenes as well as include security features such as PKCE out of the box.
Relevant github issue: https://github.com/aws-amplify/amplify-js/issues/3732
Let's say you are developing a client side JavaScript SPA app (Angular), a backend API for this app (ASP.NET Core in my case) and you use an identity provider that implements Open ID Connect protocol (I'm using IdentityServer4).
Apparently the recommended way for securing the app is to use the OIDC implicit flow between the JavaScript app and the identity provider and if successful the JavaScript app gets an id token and an access token.
Now according to this documentation the JavaScript app is supposed to pass the access token in the headers whenever it calls the API. And I'm not sure what purpose does the id token serve in this case (besides customizing the UI in your JavaScript app)?
But this is the confusing part: The documentation also says you should never use the access token for authentication. But that is the token that my API receives in the request headers, how can it authenticate the user then? If my API receives Post(newRecord), and the API needs to internally fix some audit information on newRecord (i.e newRecord.CreatedBy = CurrentUsername), how can it do that without authenticating the caller??
I think I'm missing a piece of the puzzle. Please any help is deeply appreciated.
Short answer/suggestion
Use Access Token to access API endpoints. From API endpoints, you must use token introspection endpoint to validate token validity (active state) as well as obtain subject who authenticated at authorization server. IdentityServer provide support for this. Documentation is available from here.
Explanation
ID token is intended to be used by receiving client. It will allow your client to authenticate the end user and provide user specific customizations. This is the whole purpose of OpenID Connect (OIDC). On the other hand OAuth 2.0 provide an authorization framework. It replaces user credentials with access tokens, thus improving API access security (compared to basic authentication and storing user credentials everywhere). Hence OIDC is built on top of OAuth 2.0, you get both ID Token and Access token with OIDC flow.
But as you have figured out (and mentioned before), ID token is intended for client. There are could be exceptional cases where ID token get passed between client and a server. This is mainly when both are controlled by same party. But the access token is the key to access API endpoints, correctly.
Access tokens can be an opaque string or JWT. When it's a JWT, API can read and understand the token (self-contained). When it's opaque, only way to validate token at API endpoint is to use token introspection endpoint. If API can validate token validity, then it could grant access (authorize) request. Furthermore, if user details (subject) are available (through JWT or as introspection response), then user specific checks can be executed. This further extends to token scope values. But at the end of the day, you are authorizing the API request and not authenticating the user at API endpoint. That's the highlight. Hope things are clear now.!
Lets say I have a web API that a native application needs to make requests to. This API needs to authenticate who the user is that's making these requests via the native app. OpenID Connect seems to be the right choice since it is about authentication rather than authorization with OAuth.
The native app sends the users credentials to the IDP and gets back an access token (for authorization) and an id token (for authentication). From what I understand of OIDC, the access token would be sent to the API but the id token is only for the native client app. That doesn't make sense to me because it's the API that cares about who the user is, not the native app.
So why isn't the id token also passed to the protected resource (aka the API)? If you don't pass the id token to the API, what guarantees that the access token is secure and can be used to authenticate the user? Otherwise it would seem to lose the benefit of using OIDC over OAuth.
The OIDC Specification is designed in a way that ID tokens are always for Clients (Native app) and Access tokens are for resources (APIs). The ID tokens are always JWT tokens, but the Access tokens can be of different type.
The purpose of Access token is not to authenticate but to Authorize (Delegated Authorization). If, for some reason, the resource server wanted to know about the user, it can call the user-info endpoint.
The security/validity of token exchange can be validated in several ways:
Using encryption/signature with Public/Private key model where Authorization server encrypts / signs the access token with its private key and resource server decrypts / verifies with the public key.
Using token introspection endpoint to validate the claims, validity of the token etc..
Other attributes like AUD , AZP help in validating the issued access tokens.
Some OIDC providers use ID_Tokens to access API's - this is different to the model suggested by OIDC specification
This article has detailed explanation about these scenarios.
I would like to give the users a possibility to login with some external oauth2 provider (facebook) in my app. The client's part is running on mobile device in a native app.
I am not sure which of the approaches below should I prefer ?
Should the client send the user's access token by facebook with each request ? At each request backend asks facebook to validate the access token. Based on the validation's result, backend performs authorization and return corresponding result to the client.
Should the backend ask facebook to validate the access token only at user logon, then issue its own access token, return the access token back to the client and client will use this access token at making requests to the server to avoid contacting facebook at each request ?
I have read some questions about how to implement the auth with facebook and most of the devs are using B, but I haven't seen any explanation why is it good/bad to use A ?
What I see as benefits of the solutions:
backend doesn't need to care about issuing, refreshing, validating access tokens since this is done only by facebook's authorization servers.
this solution seems to be more effective, since it does not require to connect to facebook at each request.
Security tokens issued by Facebook are signed with a digital signature. The API server only needs access to the public key to validate the signature. There's no need at all to contact Facebook after the user authenticates.
A reason to issue your own tokens after the user signed in with Facebook could be to add claims to the token. But obviously having your own authorization server comes at a cost. It's up to you to weigh the pros and cons.
If you do decide to have your own authorization server, make sure not to write your own! There are open source options like Thinktecture IdentityServer.
I will vote for option B and here is my explanation,
Your API must authorise the request every time with some auth token , which cannot be external provider token, in such case anyone with an access token (eg: other developers) of other provider can access your api, basically there is no auth here.
When your sever issue access token, it's easy to validate and when needed could be revoked easily (eg: on password reset)
While authenticating , your server has fully control over issuing access token , so the validation is made only once and doesn't have to do every time while calling the API.