I'm relatively new to this area of securing API. Most of my career was in developing internal products for the use of the organization, or joining a product that has already implemented security (which usually does not change)
When reading about JWT and Identity server, I understood the role of signing and the need to separate authorization and authentication. But, one thing strikes me as odd:
If my user is about to get a signed token and use it to authenticate himself, and there is a "Man in the middle", listening and copying that token, could he impersonate my user? (I believe the answer is yes)
So my best option here is to use SSL on every call to my API. The token being temporary and all is not much less of a threat to security.
So, my question here is:
If I end up using SSL on my API calls, what is the signing good for? with SSL the traffic is hidden anyway and no one could tamper with it. The browser can possibly use the username and password as plain text and they won't be exposed.
What am I missing here?
I think all boils down to what purpose JWT serves in OpenID Connect protocol (OIDC).
In OIDC, ID token is a JWT. And if you go through RFC7519 - JSON Web Token, then you come across Trust Decisions section.
The contents of a JWT cannot be relied upon in a trust decision
unless its contents have been cryptographically secured and bound to
the context necessary for the trust decision
From OIDC perspective, trust decision is to authenticate the end user based on claims contained in the ID token. This can be only done if validation adhere to JWT specification. So basically it is a requirement by OIDC protocol and JWT specification.
Now about SSL. OIDC contains several other calls required to obtain final token response. These calls contain client identifiers, secrets and authorization code (depending on the flow). OIDC is built on OAuth 2.0 and OAuth 2.0 mandate SSL (TLS being the new name). Thus OIDC too require SSL.
In combination, SSL (TLS) prevents attacks during request and responses flow in wire. And JWT's signature guarantee token's authenticity independent of how it was received or which component of your application process it.
Related
I am trying to understand the purpose(s) of client secrets. Is it to prevent someone from creating a fake server that pretends to be my server? If not, what is it? And does it protect against anything else?
The client secret is used to identify the application that requires an access token in order to access a resource on behalf of the user. Only clients registered in the authentication service can request access. Not only will user authentication be necessary, the client application must also be legitimate. Otherwise someone could impersonate the client application.
This type of client authorization should only be used by confidential clients ([OAuth2 Client Types][2]).
confidential
Clients capable of maintaining the confidentiality of their
credentials (e.g., client implemented on a secure server with
restricted access to the client credentials), or capable of secure
client authentication using other means.
public
Clients incapable of maintaining the confidentiality of their
credentials (e.g., clients executing on the device used by the
resource owner, such as an installed native application or a web
browser-based application), and incapable of secure client
authentication via any other means.
When using flows with clients that cannot guarantee the confidentiality of this secret (i.e. implicit), the identity of the client cannot be verified. In those cases it can be verified by means of the redirection URI. As an additional measure, it should limit the exposure of refresh tokens.
Officially it is no longer recommended to use the implicit flow for security reasons, the recommendation for this type of clients is Authorization Code + PKCE extension. [See OBBA document][1]
For authorizing users within a browser-based application, the best current practice is to
o Use the OAuth 2.0 authorization code flow with the PKCE
extension
o Require the OAuth 2.0 state parameter
o Recommend exact matching of redirect URIs, and require the
hostname of the redirect URI match the hostname of the URL the app
was served from
o Do not return access tokens in the front channel
[1]: https://datatracker.ietf.org/doc/html/draft-parecki-oauth-browser-based-apps-02)
[2]: https://www.rfc-editor.org/rfc/rfc6749#section-2.1
Sometimes you have some ApiResources which called by Clients and there is no any user in the flow. for example fetch instagram's post using instagram's api. now instagram wants to control client behavior so client should be authorized for instagram befor any api call. in this situation you need define some secret for each client to identify them.
This an example of client's secret usage.
I am learning more on Oauth2 concepts and is very much interested in using Spring Oauth2 module. I am a bit lost when learning about access tokens. How can we prevent the access_tokens from being compromised? I understand that the whole token exchange happens using HTTPS, however when a client can access to a resource using HTTP. Also, the access_token could be short lived, but it does have a window where it can be compromised. Is my understanding correct?
How can this be prevented? I see some mention of token_secret that could be passed along with the access_token, but I am not sure if Spring’s OAuth 2 implementation uses it.
What is the Access Token vs. Access Token Secret and Consumer Key vs. Consumer Secret
Please correct me if I am on a wrong track. Thanks.
You are right. An access token can be compromised through several threats (see RFC6819 for some threat models).
But some specifications (or ongoing specification) add ways to prevent access tokens from being compromised or to help you to limit bad effects if stolen.
Revoke access tokens: RFC7009
Bind tokens to the SSL connection: OAuth 2.0 Token Binding
A Method for Signing HTTP Requests for OAuth
PoP access token type and RFC7800
I am implementing an app that connects to an OAuth2 server and it gets back a Json Web Token (JWT). I am passing the token along and I want to independently validate that the token came from the issuing source.
I can do this, no problem, with the public key from the issuing source. I have it available to me for now. Everything works.
But what if the OAuth server changes the signing key? How does the validating app get the new key? Is there a "best practices" convention for sharing the public key from an OAuth2 server? Do we just expose it from an endpoint on the auth server?
There's no solution that is standardized as part of the OAuth 2.0 protocol suite (today).
It was considered to be a single-domain problem that would be solved in various ways that were considered to be out of scope for the core OAuth specifications (much like the API between Resource Server and Authorization Server is/was), and much like any PKI based mechanism in general works today.
But OpenID Connect is a cross-domain SSO protocol that was built on top of OAuth 2.0, which also defined a more standardized option of dealing with key distribution in the form of JWKs URIs as part of the Discover, see the jwks_uri entry at:
REQUIRED. URL of the OP's JSON Web Key Set [JWK] document. This
contains the signing key(s) the RP uses to validate signatures from
the OP. The JWK Set MAY also contain the Server's encryption key(s),
which are used by RPs to encrypt requests to the Server. When both
signing and encryption keys are made available, a use (Key Use)
parameter value is REQUIRED for all keys in the referenced JWK Set to
indicate each key's intended usage. Although some algorithms allow the
same key to be used for both signatures and encryption, doing so is
NOT RECOMMENDED, as it is less secure. The JWK x5c parameter MAY be
used to provide X.509 representations of keys provided. When used, the
bare key values MUST still be present and MUST match those in the
certificate.
This would expose the key material over HTTPs protected channel, effectively leveraging the SSL CA for publishing and rollover of JWT signing key material.
At some point the jwks_uri definition may be part of the standardized OAuth 2.0 protocol extensions as well, but for now you'd have to rely on a custom agreement between Client and Authorization Server to do so. That may not be too hard to implement yourself though.
You may get lucky if your Authorization Server happens to be an OpenID Connect provider as well and uses the same key material for signing ID tokens as well as JWT access tokens.
Updated 4/22/2019: the Authorization Server metadata document is now also standardized it its own OAuth 2.0 extension OAuth 2.0 Authorization Server Metadata RFC8414
I have been reading about JWT.
But from what I read it is not an authentication mechanism but more like a crucial component in a Authentication mechanism.
I have currently implemented a solution which works, but it was just to try out JWT and see how it works. But what I am after now is how one should make use of it. From my experience of it its basically just an encryption mechanism that gives you a unique encrypted key. You are also able to put information inside of this token.
I am wanting to implement it in terms on a ASP.NET web api 2 to be consumed by a mobile application.
So step 1:
app => Server : Login (user, pasword)
Server => app : Login OK, heres your JWT
app => server : Get my profile (sends JWT with request)
Server then decrypts JWT and determines the requests Identity.
Now this is just my understanding of it, Look I could be on the totally wrong path.
Is the Ideal of JWT so that you dont have to authenticate on every request? I just authenticate the users credentials once (on the initial login) and there on after the server can simply use JWT and no have to lookup the users pw and user in the DB?
I just want to use the JWT to Identity who the user is. I will then authorize then after i have authenticated them. As I know there is a big confused with the new MVC and Authentication and Authorization.
So what my question comes down to.
How can I safely and effectively Implement a Authentication Mechanism Using JWT?
I don't want to just cough something up that seems to work and not have any Idea of the security implications. I am sure that there exists a source some where that has possibly designed a secure mechanism that would suit my requirements.
My requirements are:
Must only have to check db for users credentials once off per session? Due to the use of bcrypt using a lot of resources to compare passwords.
Must be able to identify the user from their request. (I.e who they are, userId will be sufficient) and preferably without accessing the DB as well
Should be as low overhead as possible, with regards to resources on the server side processing the request.
If an intruder had to copy a devices previous request, then he should not be able to access the real users data. (obviously)
Thanks
Your understanding of JWTs is good. But here are a couple corrections and some recommendations.
Authentication and Authorization
JWTs have nothing to do with authentication. Hitting your DB and hashing passwords only happens when you authenticate on creation of the JWT. This is orthogonal to JWTs and you can do that in any way you like. I personally like Membership Reboot, which also has a good example of using JWTs.
Theoretically, you could have the user enter a password once a year and have the JWT be valid that entire year. This most likely not the best solution, if the JWT gets stolen at any point the users resources would be compromised.
Encryption
Tokens can, but don't have to be encrypted. Encrypting your tokens will increase the complexity of your system and amount of computation your server needs to read the JWTs. This might be important if you require that no one is able to read the token when it is at rest.
Tokens are always cryptographically signed by the issuer to ensure their integrity. Meaning they cannot be tampered with by the user or a third party.
Claims
Your JWTs can contain any information you want. The users name, birthdate, email, etc. You do this with claims based authorization. You then just tell your provider to make a JWT with these claims from the Claims Principle. The following code is from that Membership Reboot example and it shows you how this is done.
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var svc = context.OwinContext.Environment.GetUserAccountService<UserAccount>();
UserAccount user;
if (svc.Authenticate("users", context.UserName, context.Password, out user))
{
var claims = user.GetAllClaims();
var id = new System.Security.Claims.ClaimsIdentity(claims, "MembershipReboot");
context.Validated(id);
}
return base.GrantResourceOwnerCredentials(context);
}
This allows you to control with precision whom is accessing your resources, all without hitting your processor intensive authentication service.
Implementation
A very easy way to implement a Token provider is to use Microsoft's OAuth Authorization Server in your WebAPI project. It give you the bare bones of what you need to make a OAuth server for your API.
You could also look into Thinktecture's Identity Server which would give you much easier control over users. For instance, you can easily implement refresh tokens with identity server where the user is authenticated once and then for a certain amount of time (maybe a month) they can continue getting short lived JWTs from the Identity Server. The refresh tokens are good because they can be revoked, whereas JWTs cannot. The downside of this solution is that you need to set up another server or two to host the Identity service.
To deal with your last point, that an intruder should not be able to copy the last request to get access to a resource, you must use SSL at a bare minimum. This will protect the token in transport.
If you are protecting something extremely sensitive, you should keep the token lifetime to a very short window of time. If you are protecting something less sensitive, you could make the lifetime longer. The longer the token if valid, the larger the window of time a attacker will have to impersonate the authenticated user if the user's machine is compromised.
I've written detailed blog post about configuring the OWIN Authorization server to issue signed JSON Web Tokens instead of default token. So the resource servers (Audience) can register with the Authorization server, and then they can use the JWT tokens issued by Token issuer party without the need to unify machineKey values between all parties. You can read the post JSON Web Token in ASP.NET Web API 2 using Owin
For the formal concept . The Authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.
Let’s see the real life example
Imagine that your neighbor has asked you to feed his pets while he is away. In this example, you have the authorization to access the kitchen and open the cupboard storing the pet food. However, you can’t go into your neighbor’s bedroom as he did not explicitly permit you to do so. Even though you had the right to enter the house (authentication), your neighbor only allowed you access to certain areas (authorization).
For more detailed and for users who like more STEP BY STEP implementation on practical use of JSON Web Token in WEB API. This is must read post Secure WebAPI Using JSON WEB TOKEN
Updated to use: System.IdentityModel.Tokens.Jwt -Version 5.1.4
I'm considering using authenticated encrypted JWT tokens to authenticate / authorized access to an ASP.NET Web API application.
Based on what I've read so far, it seems to me like it is an option to generate JWT tokens from a token service and pass them to Web API via the http authorization header.
I have found some good code examples on implementing the JWT creation and consumption (Pro ASP.NET Web API Security by Badrinarayanan Lakshmiraghavan).
I'm trying to understand if I need a full OAuth implementation to support this, or if I can simply pass the tokens along in the auth header.
Assuming the tokens are properly encrypted and signed, is there any inherent security flaw in keeping things simple without having to use OAuth?
Trying to keep things as simple as possible for my needs without compromising security.
It is not that you must always OAuth when you use tokens. But given the fact that your application is a JavaScript app, you would be better off implementing a 3-legged authentication. Thinktecture identity server does support implicit grant. But if the client application getting access to the user credential is not a problem for you, your JavaScript app can get the user ID and password from the user and make a token request from a token issuer ensuring the user ID and password are not stored any where in JavaScript app (including DOM). This request for token can be a simple HTTP POST as well and it does not need to be anything related to OAuth. If your end user will not enter the credentials in the client application, OAuth implicit grant is the way. BTW, you don't need to encrypt JWT. TIS issues signed JWT and that will ensure token integrity. But if you are worried about the confidentiality, you can use HTTPS to both obtain the token as well as present the token.
It looks like you don't really need auth delegation as the one provided by OAuth. Isn't HMAC authentication enough for your scenario ?. With HMAC, you will not have to deal with JWT at all. This is an implementation I made for HMAC authentication for .NET
https://github.com/pcibraro/hawknet
Pablo.