Authenticating with Web API - asp.net

I am using ASP.NET WebAPI for a web service that I am building. He web service will use the Identity service to authenticate users.
I am a bit stuck as to how to authenticate users externally. Our current system is very basic- we send a username and password in the XML request as a separate field and it is all done in 1 request.
From what I can see from looking on Google, the best way is to request a token from the Ali and then pass this token in subsequent requests. Is there a way where I can do it all in 1 request (that is, send to the API my request for data as well as the username/password or perhaps an API key in a single request?)

From what I can see from looking on Google, the best way is to request
a token from the Ali and then pass this token in subsequent requests.
Is there a way where I can do it all in 1 request (that is, send to
the API my request for data as well as the username/password or
perhaps an API key in a single request?)
I'm not sure why your web service want to know user's username and password in Token based Authentication.
In Token based Authentication, your web service should not ask for user's username and password.
Instead, user first verifies the user name and password using a token issuer that your service trusts.
Upon successful verification, the token issuer provides the user with a token. Once the user has that token, it uses it to call your service.
For that, you do not have to reinvent the wheel. Here is JwtAuthForWebAPI nuget package for OAuth2 and OpenId Connect.

It is not secure at all to keep sending username/password with each request, you need to configure your api to issue access tokens for specified life time i.e. 24 hours. To do so you need create and end point (/token) which accepts the username/password validate the combination then issue an access token.
The client which receives this access token is responsible to store is securely and transmit it with each request to an any protected resource using the request "Authorization" header using bearer scheme.
As well you can not do this in one request, you need to obtain the access token at the beginning the you keep calling your protected resources using this access token until it is expired.
You can read more about this in my detailed blog post about Token Based Authentication in Web API

Related

Why connection token passed in the URL in Signal R?

I got a website to handle all security issues raised by a software during Pen Testing. Please refer to the following screen shot:
jquery.signalR-2.4.1 is being used in the project (ASP.NET MVC). I need to give explanation to the security team about the use of above URL, why it is showing under a GET request. Is there any threat for the application? If yes how to remove the connection string from the query string inside the URL? If it's an inbuilt process or method what's the exact use?
It's a connection token, not a session/security token. This is documented in Microsoft's SignalR security section of the documents. I would refer your security team to this information as they are not aware of the difference here and how it is used. Especially the bolded portion below:
Here it is in case the link changes -
SignalR's connection token isn't an authentication token. It is used to confirm that the user making this request is the same one that created the connection. The connection token is necessary because ASP.NET SignalR allows connections to move between servers. The token associates the connection with a particular user but doesn't assert the identity of the user making the request. For a SignalR request to be properly authenticated, it must have some other token that asserts the identity of the user, such as a cookie or bearer token. However, the connection token itself makes no claim that the request was made by that user, only that the connection ID contained within the token is associated with that user.
Since the connection token provides no authentication claim of its own, it isn't considered a "session" or "authentication" token. Taking a given user's connection token and replaying it in a request authenticated as a different user (or an unauthenticated request) will fail, because the user identity of the request and the identity stored in the token won't match.

Provide a new token based on the refresh token without going to the client - JWT - Asp.net core

I have found many links but I didn't get the solution for my problem.
I am trying to implement the jwt refresh token in asp.net core.
For storing the refresh token, I have created the table.
Based on the jwt suggestion, for SPA application, we should not expose refresh token to the client. https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
So I have planned like,
On user login, create the access token and share to the client
Create a refresh token for the access token and store it in the database and store it in HTTP only cookie
When user access to the authorized controller and action, If access token expire, I want to generate new token based on refresh token.
But,
In many places, I have found like, user will send a request. If it is unauthorised, then user will request for the new access token with the stored refresh token (local storage or something else) and again call to the valid api request.
I don't want to that as mentioned in the last paragraph(is that right one?).
When user send a request, if it is invalid, I want to validate the token in the server side itself and need to provide new access token and proceed with the last api call.
Is there any solution for this implementation like interpreting the authorize and validate?
In my opinion , it is dangerous to use/keep refresh token in SPA apps. Refresh token is powerful instrument , which is almost as powerful as the password itself . Store it in cookies or localStorage and both of these options are inherently insecure as they’re vulnerable to CSRF or XSS attacks against the client application . So i think it's better to just keep access token and do silent sign-in to renew it when access token expires.
So i don't think it's a good idea to return and use refresh token if client app is SPA application even using Code + PKCE .

AWS Cognito hosted UI returning id_token in URL

I am using AWS Cognito's hosted UI for user login. The id token is returned as part of the URL as described in https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html. Namely,
You can find the JSON web token (JWT) identity token after the #idtoken= parameter in the response. Here's a sample response from an implicit grant request. https://www.example.com/#id_token=123456789tokens123456789&expires_in=3600&token_type=Bearer
However, putting sensitive data in a query string is considered a bad practice (Is an HTTPS query string secure?). Does AWS Cognito support a more secure way of returning the id token?
Instead of token you can ask cognito to send you the Authorization code.
From Documentation:
The authorization code grant is the preferred method for authorizing end users. Instead of directly providing user pool tokens to an end user upon authentication, an authorization code is provided. This code is then sent to a custom application that can exchange it for the desired tokens. Because the tokens are never exposed directly to an end user, they are less likely to become compromised.
Source: https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/

Create session oriented API's in asp.net Framework 4.0

I am working on a project where mobile apps connects to website through a set of API's. I considered creating API's using "Generic Handlers". This was seems to be working fine until restriction are defined for sensitive data. User has to be authenticated before he makes request for data.
I created a login API where user credentials are validated and a encrypted string which contains the same credentials which he provided at the time of login are returned back to the user after successful validation.
Each time a user makes request after successfull login, an encrypted string was supplied back to server in header. On server side, the encrypted data is decrypted and validated against with the credentials stored in DB. This step is unnecessary as user is recently authenticated. Is there anyway I can avoid authenticating user for each requests. I am planning to go with WCF services where Session can be effectively used to achieve the same (is this is something good idea?)
I did the same steps as you are doing for my API's. Here are some of the changes I made in the authentication part.
Client sends his credentials (username and password) to /api/login
Server validates the credentials and forms an encrypted string with identify of user and some necessary data like expiry date. Call this as token.
var tokenStr = "user_id=1234;expire_date=" + DateTime.Now.AddMinutes(20).ToString();
var encToken = AESCryptoService.Encrypt(salt, tokenStr);
Return this encrypted token to the client
Client sets this token in the HTTP header (X-App-Token) to make future API calls.
Server detects and decrypts this token. Here you can trust this token if decrypts with your salt. Get the user_id and set the current thread principal and proceed with the request.
If the token expires (read expire_date) then return 401 Authentication request, so that the client can request the token again.
You can also use SHA-1 or MD5 or some signing/encryption mechanism to make sure that the token string cannot be altered other than you.

Workflow of JWT authentication

I'm tasked with creating a service-oriented ecosystem for a client. The whole thing is going to be REST based and built in ASP.NET, but my question is technology-agnostic. We want to have a centralized authentication service that issues JWT tokens and claims that are trusted by the other services in the environment.
My issue is this - what's the first thing that a web client (browser) requests? All of the diagrams I've seen (I'll try to add a couple of example links) make it seems as if the client needs to be self-aware and realize that they're going to need a token before they make the first request to the functional REST service, which seems, well, janky to me.
The way I want it to work is that they just attempt to access the secured resource, but there's no auth token with the request my REST service challenge them for user/password, but then delegate the authentication to my auth service. So:
Browser requests restricted resource on REST service
REST service returns 401
Browser gathers credentials, sends to same web service
REST service connects to the authentication service, passing along the Auth header from the client's request
Auth service creates the JWT token and returns it to the REST service
REST service validates the JWT and replaces the Auth header with the JWT token
JWT token is persisted for subsequent requests, up to expy setting
...am I completely off about this? Does the web client need to know that there's a separate auth service involved and make one request there to get their JWT, and then a second request for the REST resource passing the JWT? That seems clunky to me, I hope that's not the idea.
Also, another n00b question - is the JWT token automagically kept by the web clients and re-sent with every request so I don't have to go through the auth service step each time? Is that what the expiration setting is for?
TIA.
See figure 1 here for an example of what I mean: http://msdn.microsoft.com/en-us/library/hh446531.aspx
Starting with your last question will make the rest of the answers clearer:
"...is the JWT token automagically kept by the web clients and re-sent with every request.." - The idea is to issue JWT once, send it to the client so client can save it and send it on each subsequent request. This way your front-end app will send username and password just once and then use JWT for authentication. You will have to store the JWT using browser storage (local or session) or cookies (common fallback for older browsers).
"...Does the web client need to know that there's a separate auth service involved..." - You will need to send the username and password to a service in order to have the JWT issued. You could implement it with just one request, but you need to send credentials to the service (provided by the user), receive JWT as part of response and store it (as above). It might be easier to do it on a separate request, depending on requirements and implementation.

Resources