I have mvc5 application with custom login implementation. Once i got the credentials from user am making post and getting the token to validate the user. Owin Token implementation in separate class library project.
[HttpPost]
[AllowAnonymous]
public ActionResult Login(UserLoginViewModel model)
{
string baseAddress = "http://localhost:4312";
Token token = new Token();
using (var client = new HttpClient())
{
var form = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", "jignesh"},
{"password", "user123456"},
};
var tokenResponse = client.PostAsync(baseAddress + "/otoken", new FormUrlEncodedContent(form)).Result;
//var token = tokenResponse.Content.ReadAsStringAsync().Result;
token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() }).Result;
........
}
}
I am not sure how to make call /trigger the token implementation in class library project from mvc application. because class library project is not executable project. is it possible way of implementing token based implementation in separate class lib and make use of that implementation in different application (mvc and webapi).
my layer
UI(MVC) -> Authentication project (Owin class libarary) -> entity framework
any ideas?
Yes you can, but you need to expose your application login through an API of some sort.
For example you can create a token server which is responsible for authentication of both your API and you MVC project - an external provider - like Google or Facebook for example.
This is also the best way to share the same token between your two applications (MVC and API).
Check this article, it's extremely clear.
Hope it helps :)
For token based authentication, you need to use configure your mvc application or webapi to issue token. class library cannot issue token.The primary reason is that, you need to call the url configured to fetch the token eg.http://localhost:8080/api/gettoken.
So, either use webapi to issue token or mvc app to issue token.
Related
Before posting this question I' ve done lots of research in the Internet, I' ve found some stuff, but I wasn't able to find something that fits my case.
So please provide me the right direction or code snippets to go on.
I'm developing an app in .NET 6 which consists of 2 projects: Blazor WASM project for the client-side and a WEB-API project for the API's of my app.
At the moment, I've successfully implemented authentication from a central Identity Server 4. I receive "id_token" and "access_token" and use them to
secure access to my web-APIs from unauthenticated users.
The problem is that now I want to implement "role-based authorization". The facts are:
I cannot modify the code of the common Identity Server I use.
I have the users, the roles and their connection inside my app's database.
I think that the right solution here is implementing a MIDDLEWARE which reads the roles from my database and adds them into the "Claims".
Where should I develop the middleware? Web-Api project, blazor project or both???
If I developed a middleware in the Web-Api project (where by default there is already a pipeline) which adds roles into the Claims of "access_token",
the blazor project wouldn't work bacause of the modified token, right???
Could you help me with code snippets or provide me the right directions?
Thank you for your time!!!
Authorization is solely an API responsibility:
The Blazor app sends up an access token to identify the user, via the subject claim
The API verifies the JWT on every request, then looks up other claims for that subject
The extra claims can be cached for subsequent requests with the same access token
My sample .NET API shows one way of doing this and building a custom ClaimsPrincipal. Once you've done that, .NET's standard authorization techniques such as the [Authorize] attribute will work based on the ClaimsPrincipal's contents.
Authorizer class
Blog post
The client sends the access_token in every request. The server validates the access_token and then creates a ClaimsPrincipal with the claims that were included in the token. In your server can add additional claims to the ClaimsPrincipal using the OnTokenValidated event. Example:
.AddJwtBearer("Bearer", options =>
{
options.Events = new JwtBearerEvents
{
OnTokenValidated = async context =>
{
var user = context.Principal;
var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
// Get DbContext. If you don't use Entity Framework request your own data access service.
//var dbContext = context.HttpContext.RequestServices.GetRequiredService<AppDbContext>();
// Retrieve user roles from database and create a list of role claims.
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, "admin")
};
var claimsIdentity = new ClaimsIdentity(claims);
user.AddIdentity(claimsIdentity);
await Task.CompletedTask;
}
};
});
Then in your controllers you can check for the role using [Authorize(roles = "admin")] or User.IsInRole("admin");.
I am very new in implementing OAuth 2.0. I have implemented web-reference (ASMX file) in my xamarin project. Now I need to implement OAuth 2.0 for authentication. But I am not sure if ASMX supports OAuth2.0 or not. Do I need to implement WCF instead of Web refernce(ASMX) or is it possible in web reference (ASMX) to implement the OAuth2.0?
One possible solution is to add the token aquired from the authority to the Authorization header.
Your code could look similar to this:
var redirectURI = Windows.Security.Authentication.Web.WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
var _authContext = new AuthenticationContext(authority);
var tokenResult = await _authContext.AcquireTokenAsync(serviceResourceId, clientId, redirectURI);
if (tokenResult.Status != AuthenticationStatus.Success)
{
//Not authenticated
return;
}
var svc = new YourServiceReference.YourClient();
using (var scope = new OperationContextScope(svc.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = tokenResult.AccessToken;
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = svc.MyFunction();
//Do something with the data
}
Tricky - this is how mobile OAuth solutions work - but it is a big job:
Your Xamarin app would need to implement Mobile SSO to sign users in
Users of your Xamarin app would be redirected to login via an Authorization Server / Identity Provider after which they will receive an OAuth access token
After login your Xamarin App would then be able to call an API with the token and act on behalf of the user to get data
The API would need to validate received access tokens
SOLUTION PARTS
API: ASMX is an old technology so if you are working on the Microsoft stack you would use something newer such as a .Net Core Web API
MOBILE APP: The harder part of the solution will be implementing Mobile SSO, if you have not done so already.
How much of this solution exists already?
what is the best way to limit access to a webapi 2 controller within a MVC project to only the hosted App Service?
I have created a endpoint which my MVC client is accessing. The entire application is published to azure through an app service. How can I now protect the endpoint from being called outside of the application context?
Based on your comments you should consider restructuring your solution.
Consider moving your Web API to an independent project. This way your API is decoupled from your MVC app and you can deploy and scale it,if required, independently.
Move the MVC client app in it's own independent project
For authentication I would consider implementing an authorization server (again in an independent project) that issues tokens to the client (in your case the MVC app) and the client would then access the API using this token. For implementing an auth server you have a couple of options
Use the ClientCredentials grant using IdentityServer4
Use the OWIN OAuth middleware to implement your auth server with ClientCredentials grant
There are other Oauth implementations that you could use too.
Having a dedicated authorization server clearly separates out the identity responsibility allowing you to control access for other future clients and possibly restrict access to only certain endpoints (aka scopes).
You could use an API key in the request's header to filter out unwanted request.
1. Implement a customer authorization attribute (AuthorizationFilter) class.
[HttpPost, AuthorizationFilter]
public CustomerInfo GetCustomerInfo(CustomerInfoRequest request)
{
return Business.GetCustomerInfo(request);
}
2. In your controller class
public override void OnAuthorization(HttpActionContext ctx)
{
if (!VerifyHeaders(ctx))
{
ctx.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
return;
}
base.OnAuthorization(ctx);
}
private bool VerifyHeaders(HttpActionContext ctx)
{
IEnumerable<string> values = new List<string>();
//Read the API key from the request header
ctx.Request.Headers.TryGetValues("ApiKey", out values);
var apiKey = values?.FirstOrDefault();
return CheckApiKey(apiKey);
}
private bool CheckApiKey(string apiKey)
{
//Verification is done here
return true;
}
The request should contain API key which will be verified by "OnAuthorization" method.
I've got a IDP implemented in IdentityServer 4. My web app client(implemented in Mvc 5) authenticates with the IDP but now I need to get the access token from the request.
A way to do that in .Net Core is to use the Microsoft.AspNetCore.Authentication.AuthenticationTokenExtensions like so:
HttpContext.Authentication.GetTokenAsync("acccess_token")
I would like to be able to do the same in my .net Mvc5 web app client but I can't find any nuget package or namespace that has a similar implementation. It is important to be able to do this in MVC5 and not .net Core. Anyone came across this before?
PS- Also worth to mention that I'm using OpenIdConnect
The recently released 4.1.0 version of Katana now supports the SaveTokens property (backported from ASP.NET Core).
In order to get the access token:
Update the Microsoft.Owin.Security.OpenIdConnect package to 4.1.0 (or newer)
Configure SaveTokens in your Startup class:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
// Other options removed for readability
SaveTokens = true,
// Required for the authorization code flow to exchange for tokens automatically
RedeemCode = true
});
Read the access token in your Controller:
var result = await Request.GetOwinContext().Authentication.AuthenticateAsync("Cookies");
string token = result.Properties.Dictionary["access_token"];
In your controller you can get the token using this code:
var token = ActionContext.Request.Headers.Authorization.Parameter;
I spent some type before I understood, we need to send a string as an argument of AuthenticateAsync which is used in AuthenticationType and SignInAsAuthenticationType.
I hilly recond to use CookieAuthenticationDefaults.AuthenticationType because it will save you from typos.
I know this is very common question. But I really do not know how to integrate it.
I want to add authentication to my web api services. Right now I have created one console application to call service's method.
I have gone through this blog. I just want to implement authentication filter as mentioned in this article.
I want to know how can I pass credentials along with HTTPClient from my console application, fetch those things to web API and authenticate them.
I have created authentication filter but it does not invoke AuthenticateAsync method of authentication filter.
To pass http client I have done this:
public void GetData()
{
HttpClient cons = new HttpClient();
cons.BaseAddress = new Uri("http://localhost:50524/");
cons.DefaultRequestHeaders.Accept.Clear();
cons.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = Encoding.ASCII.GetBytes("Ankita:ankita123");
var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(data));
cons.DefaultRequestHeaders.Authorization = header;
//MyAPIPost(cons).Wait();
MyAPIGet(cons).Wait();
}
Teaching you how to implement authentication in Web API will take a lot of time. You better stick to online tutorials.
The blog you've read tackles about different authentication for ASP.NET. Since you've tagged your question as ASP.NET Web API 2, I would suggest using a token-based authentication utilizing OWIN middleware. Check this out. The guide uses a console application for checking the requests to the web API.
The gist of it is...
Client > Token Provider (Generate token for valid user) > Web API > Check if Token is Valid (Existing and not expired) > Authenticate!
Considering you are trying to access the API with an HttpClient, you can pass it an instance of HttpClientHandler when creating it, which allows you to set the credentials that will be used when it performs requests:
new HttpClient(new HttpClientHandler { Credentials = new NetworkCredential(userName, password) })
Hope it helps!
I have successfully implemented authentication using this article. In that filter attribute is implemented.