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.
Related
I'm having a hard time figuring a good way to implement Oauth 2.0 and OpenID Connect authentication alongside an existing internal email+password authentication for a B2B Web app's API using Spring security.
We have a backend REST API that is a Spring Boot servlet application which currently authenticates users with OAuth 1.0 and the password grant. The front-end is an Angular single-page app through which users must log in with their username and password. The API's /oauth/token endpoint then delivers an opaque access token to be used for fetching secured resources that are then displayed within the app.
We'd like to add the possibility to log in using external authentication with OpenID connect, which is a perfect opportunity for switching to OAuth 2.0 and JWT tokens. Our API would then accept JWT tokens it delivered as well as external JWT tokens emitted by accepted issuers.
Reading and validating JWT tokens won't be a problem using Spring security's OAuth Resource Server. However things get complicated with how to make the classic username+password login flow work with JWT tokens.
We thought about delivering JWT access tokens the same way we used to with our old OAuth 1.0 tokens. The thing is, newer OAuth specifications advise against using the password grant, plus it simply isn't supported in the Spring authorization server project we're planning to use. The authorization-code flow w/ PKCE seems like too much for this case as we do not want the back-end API to render a login form but use credentials entered in the existing login form that is part of the single-page app.
I've read a lot about not using OAuth for 1st party login since its primary use is for external authentication, but again, that doesn't apply since we also want 3rd party authentication.
What would be a secure way to implement a Spring boot authorization server that can deliver JWT access tokens to a 1st party client in exchange for a user's credentials, all this using the existing log in page, and given the password grant type no longer being supported?
I thought about implementing a preliminary step that would be a POST request with Basic authentication to a /login endpoint that just returns a 200 HTTP status, then proceeding to the /oauth2/authorize request that would deliver the authorization code immediately without redirecting since my session is authenticated.
I'll be happy to provide more details if needed. Here are the resources I'm using for this project.
What about setting up an authorization-server capable of identity federation?
In such configuration, the authorization-server is responsible for providing with identities, proxying one or more sources (your existing user database for instance, plus maybe Google, Facebook, Github, etc.)
Keycloak does it for instance.
From the client point of view (your Angular app), the authorization-server is used to get:
access-token: put in Authorization header of requests to secured resource-server(s) (can be a JWT or an opaque string, doesn't matter, clients should not try to extract data from access-tokens)
refresh-token: send to authorization-server to renew access-token before it expires
id-token: get user-profile data (email, username, profile picture, etc.)
You should have a look at https://github.com/damienbod/angular-auth-oidc-client for connecting an Angular app to an OIDC authorization-server.
From resource-server point of view, access-tokens are the source ofr setting-up security-context, either by decoding and validating a JWT locally or with token introspection on authorization-server.
Have a look at those tutorials for such resource-servers configuration.
I don't want to roll my own security anymore and am looking at using OpenID Connect with my c# API and AngularJS app. I can get all that to work just fine. However, my brain cannot seem to understand how to secure my API correctly for both use cases:
Use Case 1: AngularJS SPA
My AngularJS app connects to my API and sends a bearer token identifying the user and includes user claims. This one is easy and there is tons of documentation on it.
Use Case 2: API to API
Some customers want to access my API directly instead of going through my AngularJS app. In this case, I thought I could use a Client ID/Secret for toen-based authentication which is great except then I know nothing about the user that's using the client id/secret. There could be 10 users using the same custom API that is calling my API. How do I get user info via the API call? I've seen others use API keys that they then lookup the user and create a JWT but I thought there might be an easier way. Any ideas?
The whole point of API to API authentication is that there is no user context. Or well, the user in that case is the machine trying to access your API. You would then need to design your authorization logic around that and implement scope based permissions. Alternatively, your options are to use api keys as you mentioned or if you want OAuth protocol with user context in the api to api scenario - then ResourceOwnerCredentials flow is an option.
API to API communcation
You can use Client Credentials Grant defined through OAuth 2.0. This won't require you to have end user credentials. Now this won't be OpenID Connect. OpenID Connect require the involvement of an end user and bound to authentication. OAuth 2.0 on the other hand is about authorization, checking whether the entity can access the resource.
With Client Credential Grant, your identity server will issue tokens for a specific client. So one of your API becomes the client (resource consumer). From request handling API endpoint, you can accept valid tokens and respond back with resource.
If you require fine grained access control from request handling API, you will require to use token introspection to identify to whom this token was issued. In this case, it will be identification of specific client identity and execute a logic on top of it. You can check the token introspection response to identify such details.
Alternatively, access tokens can be come in form of a JWT. If this is the case, they can be considered as self contained tokens so validation is straightforward.
We would like to have REST APIs with OAuth2 using our own user table for Authentication. Also, we need to allow Social Login. Below is the flow for social login,
Our OAuth
Client makes auth and access token URL for our servers to receive
the access token
Client sends access_token for further calls in the header as bearer
token
Social Login
Client makes auth and access token URL to Social Login server(For
ex,https://accounts.google.com/) to receive an access token
The client sends access_token for further calls in the header.
We have implemented our OAuth with Spring and working perfectly. We have questions on social login,
How to identify our own Oauth access token and social login access
token. We may have many social logins and we should able to identify corresponding social login.
How to validate and integrate with Spring Boot?
If the access tokens are just random strings, you probably cannot tell the issuer of the provided token and you cannot validate it.
I would suggest you to extend your OAuth2 server to accept third party providers (Google, Facebook ...) for authentication. This way would support both local and social users, but in your application, you would always deal with your own tokens. It would make the application security much easier (which usually means safer) and you could also configure your own scopes for access tokens. There are also ready to use solutions for it - e.g. Keycloak.
I have a Web API and AngularJS client. The API is using default authorization provider given by visual studio to generate the token on token request with grant_type 'password'.
The AngularJS client is able to get the bearer token from Web API by calling the token endpoint with credentials and later passes this token to perform authorized requests in the API.
When AngularJS sends the token on any authorized API call, how is Web API able to validate the token? Where does the token get stored?
I checked in Identity tables in SQL server, I could not find any fields to store this token information. I checked in the configuration file, it is not stored there either. Could you please help me in understanding this concept?
Raj,
By default the token is not stored by the server. Only your client has it and is sending it through the authorization header to the server.
If you used the default template provided by Visual Studio, in the Startup ConfigureAuth method the following IAppBuilder extension is called: app.UseOAuthBearerTokens(OAuthOptions).
This extension coming from the Microsoft.AspNet.Identity.Owin package makes it easy for you to generate and consume tokens, but it is confusing as it is an all in one.
Behind the scene it's using two Owin middlewares:
OAuthAuthorizationServerMiddleware: authorize and deliver tokens
OAuthBearerAuthenticationMiddleware: occurs at the PipelineStage.Authenticate, read the authorization header, check if the token is valid and authenticate the user.
To answer you questions WebAPI is able to validate the token thanks to the OAuthBearerAuthenticationMiddleware, it will ensure that the token sent through the authorization header is valid and not expired. And the token is stored only by your client, if the client loose it, it will have to request a new one.
I advise you to get deeper in the OAuth protocol, and instead of using the extension UseOAuthBearerTokens, take a look at UseOAuthAuthorizationServer and UseOAuthBearerAuthentication, it will help you to better understand how it works.
The generated token will most likely be a JWT (Get Started with JSON Web Tokens), which means it's a self-contained token that is signed with a secret/key that only the server or other trusted parties know.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.
(emphasis is mine)
This means that when receiving the token the server can ensure that:
the token was originally issued by a trusted party by checking that the signature is valid.
the token is associated with a user that has permissions to perform the following request because the token itself contains information that uniquely identifier that user.
This type of approach has the side-benefit that the server does not need to keep track or store the generated tokens in order to validate them at a later time. Since no one else has the secret/key you can't modify the token without making the signature component invalid, which would then mean a faked token would end up being rejected by the server.
This is a simplified description of what happens, there are much more details around how to issue and validate tokens correctly. You should read the OAuth2 and OpenID Connect specification to learn more on the subject of token-based authentication.
Also note that I assumed a JWT token because it's the format that currently has the most widespread adoption to accomplish scenarios like these ones and it's also the token format to use in conjunction with OAuth2 and OpenID Connect. However, it's still possible to achieve the same with other token formats.
I’m trying to get my head around how I would introduce token-based (key-based?) authentication to a web API (currently looking at Sinatra, but maybe Rails too) that would be used by a mobile client and how OAuth would fit into the picture.
So, let’s say I want to create a web service that uses Facebook for authentication and grabbing basic user data. Here, my API would be a client to Facebook’s OAuth Server, requesting an access token upon a user’s successful login to Facebook. This would then grant me access to the user’s data which I would use to create an entry in my database, storing this user-specific token with any other application information I would like linked to them.
I think I got that part right so far, but here’s where I’m a bit confused.
I think that my API would also need some form of API key to grant access to a mobile user, since I wouldn’t want to transmit and store the Facebook key on their device. Would I have to have a separate store of keys which I provide to the client to access my service? Are there any ‘best practice’ ways of doing this?
Would I have to have a separate store of keys which I provide to the client to access my service?
yes.
Are there any ‘best practice’ ways of doing this?
The simplest way would be to generate a separate authentication token on every User creation and expose that to the mobile client. Then send it with every subsequent request header.
Devise provides a simple example how to achieve that. You don't need devise for that, just provide some token generation mechanism.
#Devise.friendly_token
def self.friendly_token
SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
end
This mechanism can be extended to provide more security in following ways
Being an oauth2 provider itself.
On successfull login with facebook, you would generate an :authorization_code which the client can exchange for your own Oauth2 Bearer or MAC token within a next step. Then you can send your own Oauth2 token with every request for user authentication.
See rack-oauth2
Implement HMAC token encryption.
Generate and expose a secret_key to every client after singning in. Use this secret to sign messages along with a unique client id. The server can then lookup the secret_key for the specific client_id and verify the message.
See api-auth