Web API authorization access_token validation - c#

Now I am working with authorization with OAUTH2.0.
I want to do my own authorization server(WEB API).
I have a Dummy MVC project to test this.
I succeeded to create some access token in server(WEB API) using 'SimpleAuthorizationServerProvider'.
I have to call some API Calls but should authorized.
so I can send this call with my token like.
https://localhost/Profile?access_token=...
or can send access_token through header.
This much is OK now from my side.
But I need to validate this access_token in server side.
I can get access token from client(Dummy MVC project).
private static TokenResponse GetToken()
{
var client = new OAuth2Client(new Uri("http://localhost:2727/token"),"client1", "secret");
var response = client.RequestResourceOwnerPasswordAsync("bob", "bob").Result;
return response;
}
But could not uderstand where it's created from server side.
And Where we Can Validate the access_token in server side (Web API).
I read lot but still very much confused.
Please help me.
Thanks!!

You don't need to worry about access token on server side. Access token on server side is parsed and validated by Katana middleware. If you need more details on how access token is created/used then search for DeserializeTicket and SerializeTicket methods in Katana sources, you will find that these methods are used in conjunction with Token to serialize/deserialize ClaimsIdentity which you have pased on client side(DummyMVC).
Anyway you are using SimpleAuthorizationServerProvider from Embedded AuthorizationServer Thinktecture project which is wrapper around OAuthAuthorizationServerProvider. Am I right? I belive you want to validate credentials. In your case you can override GrantResourceOwnerCredentials.
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
// validate user credentials (demo!)
// user credentials should be stored securely (salted, iterated, hashed yada)
if (context.UserName != context.Password)
{
context.Rejected();
return;
}
context.Validated();
}
Best will be if you look at Thinktecture examples.

Related

IdentityServer4 - Delegated access tokens for clients

In IdentityServer4 you can specify an extension grand to enable delegated access tokens for users, so if a webservice needs to call another webservice during a request from a user, it can request a new access token from the IdentityServer with a valid scope and audience. My issue is, that this grant is thought to be used "on behalf of the interactive user", which leads to my question:
If my client calls a webservice which needs to call another webservice during the request, how can i create a delegated access token?
I tried to modify the example from the documentation, but the extension grand expects a token from a user, which holds a "sub" claim, and not from a client, which does not hold a "sub" claim.
The client is a daemon application, so it runs fully automated and without any user interaction, and is authenticated with the client credentials flow.
To clarify what i mean:
Here we see an use case, if a user is present:
User accesses a UI
UI redirects the user to the identity server to authenticate (With the Authorization Code Flow + PCKE). The UI gets the access token back
The UI calls an WebApi A with the access token
The WebApi A needs to access the WebApi B, but the access token was meant for WebApi A. Therefore the WebApi A asks the IdentityServer for a delegated access token to access WebApi B.
The IdentityServer provides the delegated access token.
The new access token is passed along to the WebApi B.
Here we see the same use case, but no user is present and a daemon application does the same thing:
The deamon appliaction authenticates against the IdentityServer with the Client Credentails Flow and gets the access token back
The deamon appliaction calls an WebApi A with the access token
The WebApi A needs to access the WebApi B, but the access token was meant for WebApi A. Therefore the WebApi A asks the IdentityServer for a delegated access token to access WebApi B.
How to get the IdentityServer to provide a the delegated access token for the client?
The new access token is passed along to the WebApi B.
For machine to machine (Service to service) communication you typically use the client credientials grant. This allows services to communicate even if no user is present. The userid (Subject) is typically included in the API calls that is protected using this flow.
See this article
The communication between WebApi-A and WebApi-B can be done using client credentials flow and here you don't need to pass any access token from the user. Instead you pass the subjectId(userID) and optionally some additional claims as part of the API calls between A and B. This way is much simpler and the benefit is that A-B can communicate without any user involved (for example to do workflow style communication in the background).
I have found the solution to my issue. You can extend the given example implementation of the delegation grand and extend it in a way, that a delegation token is issued for a client:
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var oldToken = context.Request.Raw.Get("token");
if (string.IsNullOrEmpty(oldToken))
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
var result = await _validator.ValidateAccessTokenAsync(oldToken);
if (result.IsError)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
var sub = result.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;
if (sub != null)
{
// The old token had a user context
context.Result = new GrantValidationResult(sub, GrantType);
}
// The "magic" is the part below
else
{
// The old token had a client context
var client = result.Claims.FirstOrDefault(c => c.Type.Equals("client_id", StringComparison.Ordinal));
if (string.IsNullOrWhiteSpace(client?.Value))
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidClient);
return;
}
context.Request.ClientId = client.Value;
context.Result = new GrantValidationResult(new Dictionary<string, object>());
}
}

Web Api OWIN - How to validate token on each request

I have two applications
Client application build on ASP.NET MVC
Authentication server build on Web API + OWIN
Have planned authentication as follow
For user login client app will make a request to authication server with logged in credential.
Authication server will generate a token and will send back to client application.
Client application will store that token in local storage.
for each subsequent request client app will attached token kept in local storage in request header.
NOW, ON SERVER SIDE OF CLEINT APP I NEED TO VALIDATE THAT TOKEN COMES WITH EACH REQUEST IS NOT TEMPERED.
Please suggest me how to validate token in each request as i don't know the key the OWIN has used to generate the token.
Is is right to write code to validate token on client app or it should be on authication server.
I am planning to shift all user management code like register user, change password to authentication server so than we can re-use it for different client app- is it right design practice?
So far i have wrote below code to just to create a POC.
=========================OWIN configuration========
[assembly: OwinStartup(typeof(WebApi.App_Start.Startup))]
namespace WebApi.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new
OAuthBearerAuthenticationOptions());
}
}
}
==============================oAuth Provided========================
public class SimpleAuthorizationServerProvider: OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (AuthRepository _repo = new AuthRepository())
{
IdentityUser user = _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
Please help,
Thanks,
#Paul
Please suggest me how to validate token in each request as i don't
know the key the OWIN has used to generate the token.
Your current setup, were you have added the app.UseOAuthBearerAuthentication() to the owin pipeline, will authenticate the user from the bearer token which is passed on each request for you.
The current user can then be found via HttpContext.Current.User.
Use the Authorize attribute to then decide which users are authorized on certain endpoints.
Here's an example where users with the role "user" are allowed to access
[Authorize(Roles="user")]
public class ValuesController : ApiController
{
}
Is is right to write code to validate token on client app or it should
be on authication server.
NO, you don't validate the token in client, if your user credentials are wrong you wont get a token at all. That's all you need to know.
And also, why should you want to validate the token in the client?
I am planning to shift all user management code like register user,
change password to authentication server so than we can re-use it for
different client app- is it right design practice?
Reusing a token provider is common. Why invent the wheel for every application? Build one great, or use a third party, and reuse it across your applications.
Use JSON Web Tokens (JWT) and claims identities, not random tokens that require keeping track of the issued tokens.
A JWT is like a passport issued by a trusted authority. The passport is signed/stamped, and you can verify that it was issued by this trusted authority and that it has not been tampered with. That means, the integrity of the access-right claim present in the token can be verified without keeping state anywhere. The only communication that needs to happen between the trusting application and the authority is an initial (secure) download of the authority's public key (used for signing the tokens).
It's also advisable that you use a standard claims schema, like OpenID Connect ( http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims )
A good book on the topic, which helped me a lot getting an understanding of all these concepts, can be found here: A Guide to Claims-Based Identity and Access Control.
One way to verify a token has not been tampered is to sign it using an asymmetric key pair, Identity Server uses this approach as seen here.
In your case if you are rolling your own authentication you will need to implement this yourself, and check on every request probably in a custom middleware that the token is valid.
If you create, sendback, save in localStorage and every thing about JWT Token as correct, you have to know that many ways are in .Net that you can to controlling per request.
Server side controlling:
If you are using Web API Core, in core you can create Middleware that runs as pipline in run time, and you can give context and check token that requested, for more infomation check: This.
If you use of Asp.net MVC, you can use ActionFilter in MVC(Asp.Net-Core have more advance ActionFilter too), that each requests goes through on and you can check every thisng abount request, for more information check: This.
ClientSide Conftolling:
After that you give Token after log in from server side, you have to save data in localstorage that your browser check per request that data, they advantage are the Expireation and every like this issue in token save in localstorage and you and browser can use of this for more information check: This.
GoodLuck.

ASP.net core web api: Using Facebook/Google OAuth access token for authentication

For serveral days now I am trying to get OAuth authentication with Google and Facebook to work within my ASP.net core web api project.
my current status is:
I have an ASP.net core Web Api project in which the users need to be authenticated
I have an angular 2 web app which should use my web api (with authentication)
I have an android app, which should use my web api (with authentication)
my goal is:
Using Google/Facebook as OAuth providers for login
later: adding own user accounts (probably with IdentityServer4)
no need to redirect to a special login website (like the IdentityServer4 solution). Just hit the facebook/google button in the app, allow access, done!
In my android and angular app I am able to retrieve the access tokens from google/facebook. Now, I want to use the OAuth implicit flow, to authenticate the user on my web api, with the given access tokens (putting the tokens into the header as bearer token)
There is my problem: is there any genric way to do this easily? I do not want to use the facebook/google SDKs for this.
I have tried following:
using IdentityServer4: With this I am able to login with facebook/google on my webapi, but there is need of a redirection to the IdentityServer4 login page. Is there any possible way of just hitting the google/fb-Button in my app and logging in, without redirection to the identityServer login page?
using the google/facebook authentication middleware (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/): But they are not validating my sent bearer token (tried countless ways to achieve proper validation). Is this even possible to use within the web api?
trying to use Microsoft.AspNetCore.Authentication.JwtBearer-Middleware and putting in the necessary options for google/facebook by myself, but also not validating (aswell countless attempts)
In the last few days, I have tried so much possible solutions, that I am totally stuck and lost track of what I need to do to achieve this. At this point I have read nearly every asp.net web api oauth tutorial/stackoverflow entry but can't figure out how to use this in my case as I want. Most tutorials are just for mvc-Websites or using IdentityServer4 with the redirection to its login page.
Any suggestions or solutions? What am I missing?
If I undertsand correctly, you already have your Facebook user token from Facebook SDK through your app.
Like you I couldn't find how to do it with an ASP.NET Core library / package. So I went back to basics.
I just call a endpoint of my api with the Facebook token, check it against the Facebook graph api and if fine then I register the user (if required) and return my JWT token as if the user logged through a classical username / password path.
[HttpPost]
[AllowAnonymous]
[Route("api/authentication/FacebookLogin")]
public async Task<IActionResult> FacebookLogin([FromBody] FacebookToken facebookToken)
{
//check token
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
var response = await httpClient.GetAsync($"me?access_token={facebookToken.Token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
if (!response.IsSuccessStatusCode) return BadRequest();
var result = await response.Content.ReadAsStringAsync();
var facebookAccount = JsonConvert.DeserializeObject<FacebookAccount>(result);
//register if required
var facebookUser = _context.FacebookUsers.SingleOrDefault(x => x.Id == facebookAccount.Id);
if (facebookUser == null)
{
var user = new ApplicationUser {UserName = facebookAccount.Name, Email = facebookAccount.Email};
var result2 = await _userManager.CreateAsync(user);
if (!result2.Succeeded) return BadRequest();
facebookUser = new FacebookUser {Id = facebookAccount.Id, UserId = user.Id};
_context.FacebookUsers.Add(facebookUser);
_context.SaveChanges();
}
//send bearer token
return Ok(GetToken(facebookUser.UserId));
}
You have to copy the custom code available in this article on medium
Creat a function in AccountController.cs
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
And paste the code given in the article

How to use ASP.net 5 Identity in web API application? User authentication based on tokens. Mobile apps

Assuming that I currently have a newly created project based on Visual Studio 2015 "WebApp" template with Individual Accounts authentication, I use Microsoft.AspNet.Authentication package and I can't always rely on cookies, because my web API should also target mobile apps:
How can I add authentication to my web API? I'm especially interested in token based authentication.
You can use basic http authentication or implement a similar one with a token or ticket passed through http headers.
Implement custom AuthorizeAttribute in your web api project. In IsAuthorized(HttpActionContext actionContext) overload you can check the authorization scheme and authorization header and then you can connect to your sessions provider and check if the user has an active session.
You must pass the login token in the authorization header, so if the token is missing that means there is no active user.
So when you login you must create and encrypt the token on successful login. Then pass this token with each request to the server.
This blog contains more information about using AuthorizeAttribute: http://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way
You can make separate table in db for storing authentication detail (AuthKey, UserID, CreatedDate, ExpiredDate, IsExpired) and make functions like CheckAuthorizationKey(string authKey), ExtendAuthorization(string authKey), ExpireAuthorization(string authKey){}
and call that functions for checking the authorization as below sample code.
public ServiceResult<LoginModel> Login(string auth_key)
{
var service = new ServiceResult<LoginModel>();
LoginModel user = new LoginModel();
if (AuthKey.CheckAuthorizationKey(auth_key) == false)
{
service.message = TemplateCodes.GetMessage(TemplateCodes.UnAuthorize, null, db);
service.status = ServiceStatus.authorization_failed;
return service;
}

Retrieve bearer token in ASP.NET WebAPI

I have a Web API with authentication enabled (bearer token). This is called by a client application and I want to protect it from anonymous usage so I would like to create a single user and create a bearer token for it.
I can create the token by calling the register and token methods, but I would like to do this from code.
As far as I know, the bearer token is not stored in the database. Can it be retrieved somehow using the ASP.NET Identity API?
I would also like to create this user from code and save the token somewhere because I need to deploy the database to multiple servers.
I do not recommend going with this approach if you have only one client who will talk to your API, my understanding that you need to issue a very very long lived access token maybe for a year and keep using this token to access the back-end API, right?
What you will do if this token is stolen? You can't revoke the access token, so it is somehow like your master key (password).
My recommendation is to use OAuth refresh tokens along with access tokens. This depends on the type of your client, you can check how this is done here http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/
The refresh tokens can be revoked and they can expire after a very long time. Let me know if you need further details to implement this.
Create a Custom Authentication Attribute and store the token hashes for users. A user can have multiple tokens. Then you can let user do what he wants - log out all other sessions when password is changed or remove sessions selectively
public class CustomAuthAttribute : System.Web.Http.AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext context)
{
var accessToken = HttpContext.Current.Request.Headers["Authorization"];
var hash = accessToken.Md5();
//store the hash for that user
//check if the hash is created before the password change or its session was removed by the user
//store IP address and user agent
var isBlackListed = ...
.....
return !isBlackListed && base.IsAuthorized(context);
}
}
If you're needing to decode the token within a WebAPI Controller function, I found this worked:
String token = Request.Headers.Authorization.Parameter;
Microsoft.Owin.Security.AuthenticationTicket t = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);

Categories