For the sake of security, what's the benefit of the id token provided by OIDC? What if id token is stolen? - security

I have read a lot about OIDC and OAuth2, I know the id token is mainly used for the client to know who the user is and whether the user is still online currently.
Furthermore, Id token can prevent a class of impersonation attacks [You can find more details in this article].
But what if the id token is stolen? Can the attacker uses the id token to impersonate a user?
In our project, we just ensure https besides the OIDC. What else security consideration should I take to mitigate the impersonation attacks?

The goal or purpose of OIDC is not to be more secure than OAuth2, and this kind of comparison doesn't make sense. They solve different problems.
Let's start with OAuth2. In very short and somewhat simplified, OAuth2 solves the problem when a website holds data of a user, and that user wants to grant access to some of their data to another website. Say you have a Facebook account, but want to allow my application to access some of your data on Facebook, or for a more concrete example, you want to allow my awesomeapp.com app to post a link to your Facebook wall. For this, my website redirects you to Facebook, you log in, get an access token, and send that access token back to my website so that I can use it in your name to get what you allowed me to.
Note that there is one thing missing. I have no idea who you are. I just had an access token, with which I can do stuff, but I don't have identity info about you. Sure, this can be abused in different ways, the access token can hold your email address or whatever, but it's limited, the size matters, and there is no standard way.
At least not until OIDC comes in the picture. OIDC provides the identity element.
The purpose of the ID token is to provide identity info, to tell me claims about who you are. It may claim what your email address is, what security groups you are in, which company you work for, or anything else. Also it may be used to download more claims, in case they don't all fit in the actual token (see userinfo). These claims come from the Identity Provider, say Facebook, which my application then has to trust of course, i.e. I will believe whatever Facebook tells me about you.
This is all possible with pure OAuth2, but there is no standard, well known way to do so (or well, it is OIDC :) ). You could invent and implement something yourself, but these things are more complicated than they may first seem to be. That's why OIDC was invented, so you don't have to. But after all, OIDC is just a way to use OAuth2 to provide identity. In the end, it's just an extended OAuth2 if you like.
As for what security considerations you need to take into account - this part of your question is way too broad and can't be answered unfortunately. Security is a very complex topic.

I'm not really a security purist so my additions to Gabor's points are from a more practical viewpoint, as someone responsible for building well architected UIs and APIs:
An id token represents proof of authentication to a UI
An id token is NEVER used by APIs, which must use access tokens instead
An id token is the only type of token a UI should ever read, and it is mandated to have a JWT format
For Web UI logins an id token provides extra security, since it enables the UI to validate tokens and protect against some types of token substitution attack - so yes - OIDC is more secure
An id token is sometimes needed in order for logout to work
You should ALWAYS use a certified security library that does this type of work for you, rather than reading tokens directly in your own code.

Related

Why do access tokens issued by AAD contain information about the user?

I read a lot about OAuth 2.0 and OpenId Connect and in theory I understand both concepts now.
But if I go into practice, some things are still confusing for me and I hope you can enlighten me in some way...
First thing is, that in all code samples how to secure a .net core API in an AAD-environment I find lines like this in the configure-section:
app.UseAuthentication()
and lines like this in the ConfigureServices section:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://login.microsoftonline.com/xxxxxxxx";
options.Audience = "xxxx-xxx-xxx-xxx-xxxx";
});
However, to access my API I am not using an ID token, but an access token what is Authorization, not "Authentication" like in the code samples.
This works - but I do not understand it 100%.
So my first question is:
Is the access token also "authenticating" in some way?
The second thing:
I read that access tokens have no standardized format. They can be JWT or not, can have an audience or not etc. For this reason you could even put user information in the token like microsoft does. The access tokens contain claims like a "family name" or "given name" etc.
Id tokens in contrast have a standardized format to ensure that authentication is done in the same way by everyone.
If people are accessing my apis with an access token, I can read their name or e-mail address with "user.identity.name" for example. This value I can use to store the information who edited something or who inserted something.
So I am fetching information about the user with access tokens!
So my second question is:
Am I doing the right thing here? Or should this be done in another way.
and:
Should access tokens ever contain information about the user?
Is the access token also "authenticating" in some way?
Yes.
Your API is validating the access token when it receives it.
This is the authentication part, when your API verifies that the token signature is valid, came from the Azure AD tenant that you trust, that it is meant for your API and that it has not expired.
The authorization is when you check what permissions the token contains.
Your API can define different permissions that are given to client applications, allowing them different levels of access.
A valid token can pass authentication, but it might not pass authorization if it lacks the necessary permissions.
Am I doing the right thing here? Or should this be done in another way.
Fundamentally your are doing the correct thing.
The token tells you who the user is that is using the client application, and if you need to know who it was who did something, that's the info you use.
However, if you really want to connect an action to a user, I suggest you use their object identifier / object id / oid instead of their name / username as those can change.
Unless you just want their display name.
Should access tokens ever contain information about the user?
In the context of Azure AD, an access token will always contain info about the user if a client application is accessing an API on behalf of a user.
This includes authentication flows like authorization code, device code, implicit, and on-behalf-of.
They all use delegated permissions aka scopes to call APIs on behalf of the user.
Thus the token contains info about the calling app and the user.
If an app acquires an access token using the client credentials flow where a user is not involved, there will be no user info in the token.
In this case, application permissions are used instead of delegated permissions in Azure AD.
An application acts as itself, not on behalf of any user.
If your API supports both of these scenarios, sometimes the tokens contain user info and sometimes not.
The part about token formats is basically correct from a specification standpoint.
OAuth doesn't define a strict format for access tokens, while OpenID Connect does define one for ID tokens.
Using an access token to call your API is definitely correct.
The ID token is only meant for the app that initiated the user authentication, not for any APIs that it calls.
That's what access tokens are for.
if you check here: https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens
in the newer access tokens, by default it follows the standard of not having any personal information about the user. which is what the standards suggest, Access tokens should not contain much or any information About the user. rather just information for authorization (things that user can access).
However you can always add the optional claims (and azure lets you do it) for personal info, but best practice suggests you shouldn't.
in terms of the addauthentication: Authentication is basically proving who you say you are. addauthentication(), basically calls microsoft azure ad to perform this task, saying hey aad please ask this person who he is, azure then checks and says ya this is a real person, but i won't tell you anything about him other than an id, and they have access to your api/application. So from your snippit, it's fine.
at this point, your serverside shouldn't have any personal information about the user, just that they have access and what scopes/roles. If it wants info about the user, it should then take that authorization (access token) and request it from whatever endpoint that token has access to (graph)
here's a great read about it: https://auth0.com/blog/why-should-use-accesstokens-to-secure-an-api/
Hopefully this helped clarify somewhat, and not add more confusion to the issue.

email-based registration using oauth2 flow possible?

Is it possible to implement the Oauth2 flow in which , instead of a specific identity provider being used in the redirect, you instead ask the user to submit an email address, and then send an authorization code to that email address, and they click the link to get issued an access token?
In this scenario, how would one make use of a state parameter to prevent CSRF? And, are there other security implications to this design?
It's possible with a custom grant type (example). Translation: this will be a scheme that is proprietary to your clients and your authorization server. You're either going to have to write a lot of code yourself or rely on a commercial solution such as one linked above. Your clients will have to understand this flow...so you won't be able to grab any oAuth-compliant app and expect that it'll work with this scheme.
A better option is to NOT go through email and NOT require a user entry of an additional authentication factor. Instead, use one of the standard grant types with a well-defined threat model. Recommendation: authorization code grant type with PKCE extension. It takes care of CSRF and many other threat vectors. See oAuth Security Best Current Practice (BCP) for more details.
As an alternative, you can perform your email-based verification routine after the oAuth flow is done.

How to authenticate and authorize in a microservice architecture

Short: How to authenticate and authorize role-based users in a microservice architecture?
Long: Say that you have the architecture given below.
I am struggeling to see what would be the best practice solution for securing such an architecture.
When i search i get alot of different answers.
"Leave authentication to a thirdparty OAuth provider". This seems like adding a lot of overhead and complexity for a rather simple application, and it may not be desireable to delegate authentication and authorization to a third party.
"Use JWT". If I am correct, then the use of JWT token is not suitable for external use (like in a SPA).
"Use a combination of opaque tokens externally and JWT internally linked in a redis/memchache". This seems like the best solution for my given situation, but my problem here is the lack of actual references to libraries/code examples.
I would higly appriciate if someone had some references of actual implementations to what i am trying to accomplish which would be:
Authentication, role-based authorization, in a microservice architecture.
There is not enough information to suggest what exactly should you be doing with architecture wrt authentication and authorization but I can tell you one of the approach that I tend to rely on.
Follow OAuth, as it gives you quite a few option, you can start with your own IDM/IAM and can later connect via social platforms.
We started of with JWT and for most part it was just a signed token (some time later we moved to signed and encrypted tokens). We created one service responsible for handling authentication and creating the JWT token. (We started with Keycloak but later moved to own service as keycloak was lil bulky for our use case)
When you say external, I am not sure what you mean by that, if is just accessible to end user IMO we can live with just a signed token. Yes all the information is visible to the user, but that is all his info and some authorization related information.
If you are passing your token to someone outside your boundaries, to an actual external system, where you do not want to share use information you can think of encrypting it, but then there will quite a lot of things that you need to think from security perspective and therefore going for either a standard security platform or a third party provider (whom both of you can trust and who puts enough thought in securing it) can help you in the long run.
Using the combination of an opaque token and JWT may be an overkill, unless you have a very strong reason against it. IMO you keep it simple to start with, make use of JWT through out, if required encrypt it. All you need will be one more service to manage authentication and creating and signing a token and you should be good.

OAuth is not secure or I didn't understand it?

I was thinking about security for my REST web Service API, and decided to take a look at others large services and how they do it. As an example I decided to study Twitter's OAuth. After reading beginners guide I'm a little be confused and shocked.
As I understood it's Service provider responsibility to authenticate user and to show User what kind of access consumer is demanding (for example it want's read only access to specific resource). But I saw service providers that doesn't inform user on what type of access consumer is demanding (and even now showing consumer's identity). The second part of problem is that consumer can show his own custom Provider Service Authentication form in IFrame, and just hide access details, they can just steal you password, or request unlimited access to you resources, they can do basically what ever they want, there are lot's of way to trick user.
As an example let's take a LinkedIn. They request your gmail username and password inside their own form, and you have no idea how they will use it. They can just steal it and store in their DB, they can OAuth with it to gmail (and they don't show gmail's page with information what type of access they request), they can do whatever they want with this information.
What I'm trying to say is not that OAuth communication protocol is not secure, but rather there are lot's of way to use it improperly to trick the user and get his credentials.
BTW there were some security flaws in OAuth protocol itself: (http://oauth.net/advisories/2009-1/) and I'm pretty sure there are more, but no one cares to find them.
I'm going to go with 'You didn't understand it.' (In your defense, very few people do.)
Let's be clear: The session fixation attack you're referring to affected OAuth 1.0, but was resolved in OAuth 1.0a, which became RFC 5849. There are no major implementors of OAuth 1.0 — the major implementors all either implemented OAuth 1.0a/RFC 5849 or they implemented one of the OAuth 2.0 drafts.
As for the username/password anti-pattern, OAuth 1.0a does not provide for a mechanism to exchange a username and password for an access token. OAuth 2.0 does, but only for the purposes of supporting installed applications. Keep in mind that an installed application could simply keylog (or similar) if it really wanted to. When it comes to security, all bets are off if an application is already running natively and unsandboxed on the client's machine. But this is actually a very different scenario than what you're talking about. Web applications in both OAuth 1.0a and OAuth 2.0 don't ever touch the username and password.
The flow for OAuth 1.0a goes like this: The application asks the provider for a request token, telling it all of the things it wants access to. The provider issues the temporary unauthorized token, at which point the client may send the user to the provider to authorize that token. The user logins in with their username and password on the provider's site and then either grants or denies access. The provider then redirects back with a verifier string that allows the site to upgrade to an authorized access token. All of these interactions are signed. If the signatures don't match on any of them, the provider will reject the request. And the user can revoke any token at any time, removing the client's ability to access their account.
There are a number of security considerations with the protocol, but if you actually read the list, it's essentially the same list of the security issues that affect almost every site on the internet. These security considerations are all very well known and very well understood. To my knowledge, there are currently no known exploitable attacks against providers that correctly address all of these security considerations.
Point being, you are much safer using OAuth 1.0a or OAuth 2.0 to authorize a third party than with any of the alternatives. If you don't feel comfortable with these, the solution is simple: Don't authorize third parties to access your account. There certainly are plenty of reasons why you might not want to do that.
It sounds like you are confused about what's not secure. As I understand it, the OAuth protocol itself, if implemented properly, is secure. It's just that it's easy to implement improperly, and users get confused because they don't really understand what they are doing.
For example, what LinkedIn is doing is all wrong. I would never give them my gmail account information in this way. In order for me to provide my gmail account information, I insist on seeing that my browser is using SSL with Google and so the root frame of the page comes from Google.
Then there is the matter of trusting Google to correctly tell me what access is being requested and by who. If I don't trust them to do this, I shouldn't be using OAuth.

What is token-based authentication?

I want to understand what token-based authentication means. I searched the internet but couldn't find anything understandable.
I think it's well explained here -- quoting just the key sentences of the long article:
The general concept behind a
token-based authentication system is
simple. Allow users to enter their
username and password in order to
obtain a token which allows them to
fetch a specific resource - without
using their username and password.
Once their token has been obtained,
the user can offer the token - which
offers access to a specific resource
for a time period - to the remote
site.
In other words: add one level of indirection for authentication -- instead of having to authenticate with username and password for each protected resource, the user authenticates that way once (within a session of limited duration), obtains a time-limited token in return, and uses that token for further authentication during the session.
Advantages are many -- e.g., the user could pass the token, once they've obtained it, on to some other automated system which they're willing to trust for a limited time and a limited set of resources, but would not be willing to trust with their username and password (i.e., with every resource they're allowed to access, forevermore or at least until they change their password).
If anything is still unclear, please edit your question to clarify WHAT isn't 100% clear to you, and I'm sure we can help you further.
From Auth0.com
Token-Based Authentication, relies on a signed token that is sent to
the server on each request.
What are the benefits of using a token-based approach?
Cross-domain / CORS: cookies + CORS don't play well across different domains. A token-based approach allows you to make AJAX
calls to any server, on any domain because you use an HTTP header
to transmit the user information.
Stateless (a.k.a. Server side scalability): there is no need to keep a session store, the token is a self-contained entity that conveys all the user information. The rest of the state lives in cookies or local storage on the client side.
CDN: you can serve all the assets of your app from a CDN (e.g. javascript, HTML, images, etc.), and your server side is just the API.
Decoupling: you are not tied to any particular authentication scheme. The token might be generated anywhere, hence your API can
be called from anywhere with a single way of authenticating those
calls.
Mobile ready: when you start working on a native platform (iOS, Android, Windows 8, etc.) cookies are not ideal when consuming a
token-based approach simplifies this a lot.
CSRF: since you are not relying on cookies, you don't need to protect against cross site requests (e.g. it would not be possible to
sib your site, generate a POST request and re-use the existing authentication cookie because there will be none).
Performance: we are not presenting any hard perf benchmarks here, but a network roundtrip (e.g. finding a session on database)
is likely to take more time than calculating an HMACSHA256 to
validate a token and parsing its contents.
A token is a piece of data which only Server X could possibly have created, and which contains enough data to identify a particular user.
You might present your login information and ask Server X for a token; and then you might present your token and ask Server X to perform some user-specific action.
Tokens are created using various combinations of various techniques from the field of cryptography as well as with input from the wider field of security research. If you decide to go and create your own token system, you had best be really smart.
A token is a piece of data created by server, and contains information to identify a particular user and token validity. The token will contain the user's information, as well as a special token code that user can pass to the server with every method that supports authentication, instead of passing a username and password directly.
Token-based authentication is a security technique that authenticates the users who attempt to log in to a server, a network, or some other secure system, using a security token provided by the server.
An authentication is successful if a user can prove to a server that he or she is a valid user by passing a security token. The service validates the security token and processes the user request.
After the token is validated by the service, it is used to establish security context for the client, so the service can make authorization decisions or audit activity for successive user requests.
Source (Web Archive)
Token Based (Security / Authentication)
This means that in order for us to prove that we’ve access we first have to receive the token. In a real-life scenario, the token could be an access card to the building, it could be the key to the lock to your house. In order for you to retrieve a key card for your office or the key to your home, you first need to prove who you are and that you in fact do have access to that token. It could be something as simple as showing someone your ID or giving them a secret password. So imagine I need to get access to my office. I go down to the security office, I show them my ID, and they give me this token, which lets me into the building. Now I have unrestricted access to do whatever I want inside the building, as long as I have my token with me.
What’s the benefit of token-based security?
If we think back on the insecure API, what we had to do in that case was that we had to provide our password for everything that we wanted to do.
Imagine that every time we enter a door in our office, we have to give everyone sitting next to the door our password. Now that would be pretty bad because that means that anyone inside our office could take our password and impersonate us, and that’s pretty bad. Instead, what we do is that we retrieve the token, of course together with the password, but we retrieve that from one person. And then we can use this token wherever we want inside the building. Of course, if we lose the token, we have the same problem as if someone else knew our password, but that leads us to things like how do we make sure that if we lose the token, we can revoke the access, and maybe the token shouldn’t live for longer than 24 hours, so the next day that we come to the office, we need to show our ID again. But still, there’s just one person that we show the ID to, and that’s the security guard sitting where we retrieve the tokens.
The question is old and the technology has advanced, here is the current state:
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for passing claims between parties in web application environment. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context.
https://en.wikipedia.org/wiki/JSON_Web_Token
It's just hash which is associated with user in database or some other way. That token can be used to authenticate and then authorize a user access related contents of the application. To retrieve this token on client side login is required. After first time login you need to save retrieved token not any other data like session, session id because here everything is token to access other resources of application.
Token is used to assure the authenticity of the user.
UPDATES:
In current time, We have more advanced token based technology called JWT (Json Web Token). This technology helps to use same token in multiple systems and we call it single sign-on.
Basically JSON Based Token contains information about user details and token expiry details. So that information can be used to further authenticate or reject the request if token is invalid or expired based on details.
When you register for a new website, often you are sent an email to activate your account. That email typically contains a link to click on. Part of that link, contains a token, the server knows about this token and can associate it with your account. The token would usually have an expiry date associated with it, so you may only have an hour to click on the link and activate your account. None of this would be possible with cookies or session variables, since its unknown what device or browser the customer is using to check emails.

Resources