I found this in another SO thread:
Steps:
User connects to OpenID enabled website.
User enters credential information.
A POST is made with a BASE64 (website to provider)
An answer is built (that contains expiration)
The website redirects the user to the provider to login.
User enters password and submit.
Verification is done.
Login!
How are step 6-8 secured? The way I see it, the client is authenticating with the provider and reporting back the result to our server.
What is stopping the client from faking the authentication result?
Primarily, the authentication result is cryptographically signed by the provider. There are also other security measures protecting against other attacks.
Quoting the OpenID 2.0 specification, section 11.:
When the Relying Party receives a positive assertion, it MUST verify the following before accepting the assertion:
The value of "openid.return_to" matches the URL of the current request (Section 11.1)
Discovered information matches the information in the assertion (Section 11.2)
An assertion has not yet been accepted from this OP with the same value for "openid.response_nonce" (Section 11.3)
The signature on the assertion is valid and all fields that are required to be signed are signed (Section 11.4)
The client can, of course, send a fake authentication result, but it won't pass verification.
Related
First of all let’s clarify we are aware that OIDC and oAuth2 are different protocols, albeit OIDC builds on the flows and mechanisms defined by oAuth2, and they also use different tokens, a JWT Identity Token used for OIDC, and a resource access token (possibly also JWT formatted, but not required to) for oAuth2; the first deals with the issue of federated authentication and the second deals with the issue of federated resource access authorisation).
Having said that, for this specific question it is more or less irrelevant what type of token we do have, as here we are interested in understanding the mechanism through which a client system trusts the legitimacy of a token (please understand client system as defined by the oAuth2 flow definition of client system plus any extra system capable of accepting those same digitally signed tokens).
For the sake of simplifying the argumentation, let’s assume that we are following an auth code grant flow. In this flow after the end-user has been redirected toward the Id/auth server, provided his credentials successfully, and being redirected back to the original "issuer client"; we can be sure that this “issuer client” can trust this token because it was obtained through a backchannel http request which provided the access code plus a client secret unknown to anybody else, so for this "issuer-client" it is trivial to trust this token. Let’s call this the “trivial case”.
Now let’s assume we have more client systems capable of potentially accepting this previously generated token -as long as that token is valid of course- (this would indeed be a form of SSO, because those systems are basically “bypassing” their end user login, by virtue of trusting this token previously generated by ANOTHER client). The question I have is how can those other clients (which didn’t issue the token initially as described previously on the trivial case) trust the legitimacy of this token?.
One way to solve the point in the above’s paragraph, would be for clients when presented with a token, to “ask” the id/auth provider if it indeed generated the token; but in different documentation & blogs I’ve seen it seems it is often the case that client systems usually accept the token without talking back to the Id/auth provider. How does this happen that the token is on itself enough for establishing trust? It is mentioned that the digital signature ensures nobody changed the token, but how can those systems know the token wasn’t generated by other -potentially malign- Identity/auth server?. Let’s say that we have a 2nd Identity/authorisation server that issues tokens identical in structure to the ones of the 1st one; under this situation, how do clients know that a token comes from auth server 1 and not auth server 2? For the clients to discern with 100% certainty that a token not only wasn’t changed, but also that was generated by the authority the clients know and trust, it seems as if the tokens need to have as part of their digital signature some piece of information which is specific to the Id/auth server that generated it and can’t be replicated by any impostor (and the clients knows how to decode).
So that is the gist of my question, how can “non issuer-clients” (when presented with a token), know without speaking to the Id/auth provider, that the received token not only wasn’t changed (for this the signature), but also know from which Id/auth provider they come from, and also how is it prevented that a “fake Id/auth provider” could generate almost identical otherwise perfect tokens.
Thanks in advance for any feedback, and sorry for my limited english, it is a complex topic and probably the question isn't formulated in the best way.
The API's that receives the tokens usually queries the token providers /.well-known/openid-configuration endpoint to download the public signing keys.
then when the API receives an access token, it can use the public key from the provider that the API trusts, and verify that the access token is genuine and has not been modified.
Inside the token there is typically also an audience claim, that specifies who the intended target is for the token and also a claim describing who issued it.
So, there are many ways for a resource that receives an access token to verify that it is trustworthy.
I implemented a simple web page where Google Sign In let users enter their Gmail and password in order to authenticate; then I made a simple server with Flask using Google Python API.
Everything is working fine, but I realized that I made the server before asking myself if I really need it: if I got it right, when user's credentials are verified after clicking on Google Sign In, the user is authenticated.
Client-side speaking, after a successful login a GoogleUser object is returned and it contains informations about the user; however, the user has already told me who he is since he provided me username and password.
So, why bother validating on a server an ID token if it is given after a successful login?
Some concepts sound contradictory to me: Google Sign-In for Websites: Authentication with backends video says that:
You can obtain an ID token upon the successful authentication
this would mean that the user is who he claims to be, but then, speaking about a server:
Note that the client libraries verify most of the information, but you still have to check if aud and iss claims are correct [on the server]
I thought that these two claims were verified on the client.
Is the GoogleUser object returned from a successful login enough to say "he is really that user"?
The ID token I send and verify in my server is necessary because there is no Google Sign-in button on the servers and is meant only for client side code?
So, why bother validating on a server an ID token if it is given after
a successful login?
The OAuth 2.0 ID Token provides the "verified" identity of the client. Since it is very easy to create an ID Token, you need to verify that the ID Token was created by a trusted Identity Provider. You verify the ID Token to prevent forgery attacks. How? By using the public key from the Identity Provider to verify the signature attached to the ID Token.
Note that the client libraries verify most of the information, but you
still have to check if aud and iss claims are correct [on the server]
I thought that these two claims were verified on the client.
In terms of security, you cannot trust anything from the client. You must verify everything. Hackers today think nothing of running scripts attacking any resource attached to a public IP address.
Is the GoogleUser object returned from a successful login enough to
say "he is really that user"?
No. The JavaScript code running at the browser can be modified. This means all data coming from the browser to your server should be consider "untrusted".
The ID token I send and verify in my server is necessary because there
is no Google Sign-in button on the servers and is meant only for
client side code?
You can implement 3-legged OAuth 2.0 which puts your server into the Authorization process. This way your server receives the Access Token, Refresh Token and ID Token. You then control what you provide to the client.
I'm aware of how SAML is used for single sign on (SSO). That is, redirection to IDP from SP and getting the user's identity from the SAML response/assertion.
My question is - Does SAML 2.0 specification define how to pass username and password as part of a SAML request xml for authentication? Note that I'm not talking about single sign on and just want authentication of username/password.
Thanks,
The SAML standard supports passing a user identifier in the <saml:Subject> field of the <AuthnRequest> (i.e. the request for authentication).
There is however no built in support for passing a password as part of the AuthnRequest. IMHO doing so goes against the principles of SAML2 as that expects the Idp to only use a password when authenticating. Normally the Idp may use any means it finds suitable to confirm the identity of the subject. That could be a password, but also a certificate or a one time pad exchange over SMS. Or something else - it's up to the Idp.
That said, there is an <Extensions> element in the <AuthnRequest> that could be used to carry a password. Doing so would require careful security considerations as the AuthnRequest contents are not designed to be kept secret. If using the Http Redirect binding the contents are logged in a web server and visible in browser history. If using the Http POST binding the password is still visible to the browser. I would suggest using the SOAP or Artifact binding to make sure the data is transferred directly from the SP to the Idp. Note however that those bindings have considerable less support in frameworks.
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 OAuth2 SAML bearer spec describes how an application can present an assertion to a token endpoint as an authorization grant. For example, Salesforce's API allows this approach to enable apps to autonomously request access tokens for a user account (as long as the user has already given permission for this, out-of-band).
I'm having trouble making sense of what the assertion means, though. Most of it is clear enough, e.g.
Issuer is the party that generated (and signed) the assertion
Subject is the user for whose account an access token is being requested
AudienceRestriction limits the audience to the token endpoint.
But I'm having trouble understanding the meaning of:
AuthnStatement -- My understanding from the SAML spec is that the issuer of this assertion is making the statement that it (the issuer) has authenticated the subject. Is this right?
SubjectConfirmation -- who is confirming what here? The SAML spec helpfully states that this element "Information that allows the subject to be confirmed". But what is confirmation? And who performs it, and how, and when, and for what purpose?
AuthnStatement element describes the act of authentication at the identity provider.
If the Assertion issuer authenticated the subject, the Assertion SHOULD contain a single representing that authentication event.
Example:
<AuthnStatement AuthnInstant="2010-10-01T20:07:34.371Z">
<AuthnContext>
<AuthnContextClassRef>
<!--Authentication method, was the client authenticated with digital cert, password, kerberos token?-->
urn:oasis:names:tc:SAML:2.0:ac:classes:X509
<!--For example, the Password class is applicable when a principal authenticates to an authentication authority through the presentation of a password over an unprotected HTTP session. -->
urn:oasis:names:tc:SAML:2.0:ac:classes:Password
urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos
</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
SubjectConfirmation element allows the authorization server to confirm it as a Bearer Assertion. Such element MUST have a Method attribute with a value of "urn:oasis:names:tc:SAML:2.0:cm:bearer".
The SubjectConfirmation element MUST contain a SubjectConfirmationData element (With exceptions) indicating the token endpoint URL of the authorization server. The authorization server MUST verify that the value of the Recipient attribute matches the token endpoint URL to which the Assertion was delivered.
Example:
<saml:SubjectConfirmation
<!-- Mandatory -->
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData
<!-- The AuthRequest sent this ID -->
InResponseTo="aaf23196-1773-2113-474a-fe114412ab72"
<!-- It was through HTTP POST token endpoint URL -->
Recipient="https://sp.example.com/SAML2/SSO/POST"
<!-- Not valid ON or After this Date and Time -->
NotOnOrAfter="2004-12-05T09:27:05"/>
</saml:SubjectConfirmation>
Yes, the AuthnStatement is from the issuer of this assertion stating that it has authenticated the subject.
SubjectConfirmation tells how an entity that wants to rely on an assertion can confirm that the subject in question is the subject referenced in this assertion. Maybe the assertion is valid, but is it for the user making the request? If the method is bearer then any subject who can present this assertion to the endpoint referenced in Recipient before the date in NotOnOrAfter is confirmed. If the method is holder-of-key then only a subject who can prove possession of the key referenced by a nested KeyInfo element is confirmed.