In a WASM Blazor application I am injecting the Http client by doing this in the top:
#inject HttpClient Http
Now I want to be able to set a username and password like in regular .NET, there you would do:
handler.Credentials = new NetworkCredential(userName, password);
However, I cannot find any property of Http where I can set my credentials, how can I set it?
It's not clear what you do as you provide almost no code to demonstrate your issue. However, it is very clear what you're striving at.
In order to authenticate and authorize users in Blazor WebAssembly App you can use Jwt authentication or OpenID connect that pass a user's credentials to a Web Api end points to verify the users, create a Jwt token, and pass it back to the front end where you can store the Jwt Token in the local storage, and retrieve it when the user logs in, accesses various resources, etc.
Note also that the HttpClient is not really the actual HttpClient. It is based on the JavaScript Fetch Api, and it is missing features like WebSockets, etc.
I've posted in this section answers about how to use Jwt Authentication and OpenID Connection. You'll have to search for those answers dealing with Jwt Authentication, as it was relatively long time ago, and I don't remember their locations. However, here is the links to Adding OpenID Connect to IdentityServer4, and Accessing token from Blazor
Hope this helps...
Related
This is sorta driving me crazy. We got a Web API that takes a JWT bearer token received via ADFS. Now I have to write a Windows Service that communicates with the API but to do that, I need that JWT token.
I tried looking on the internet but none of the solutions work. Lots of examples use the WSTrustChannelFactory but none of them show how to specify a Client ID for the ADFS application or other relevant information.
Another example is MSAL.NET which supposedly supports ADFS. But all the examples and documentation are about Azure AD, but we have an on-premise AD. Some examples also point to example code that no longer exists on GitHub.
I managed to get a token with the ConfidentialClientApplication from MSAL.NET but it‘s not working, the API says it‘s invalid. And it seems it uses response_type code, rather than id_token which I need, and there apparently is no way to change that.
Other than these two, I can‘t find anything at all about this subject.
So: How can I receive an ADFS JWT bearer token with C# from a Windows Service application using the current user context, rather than requiring a manual username and password entry?
Any pointers would be greatly appreciated.
We have a self hosted WCF REST API service (not ASP.Net). We currently support Basic and Negotiate authentication.
We would like to add support for JWT in a cookie, so that we dont have to authenticate against the DB on each call, and so we dont have to set headers. The main issue is that we want our web application, which uses the API to be able to provide links to retrieve resources for downloading without setting headers, ie rely on browser having a JWT pushed into a cookie.
We have an endpoint called /API/AuthToken, which supports Basic Authentication, but we’re not sure what the code to generate a JWT token, and pushing it to a cookie would look like. Specifically, what does the code for generating a JWT token should do.
I have not been able to find any documentation or samples on how to do this? Any leads or code snippets?
I am trying to resolve a problem with Sign-In to ADFS on premise from Angular. We have received a FederationMetadata.xml. However, all examples for angular adal require a clientId. Is that something I can get from there?
I am able to get the login url, when I put the AddWsFederation to my C# Controller and call HttpContext.ChallengeAsync. However I would like to have more clients on one server, so I would prefer something more flexible. MS examples have only one clientId in the web.config and setup them at the start.
Thank you very much for any piece of advice.
The metadata file is for a SAML or WS-Federation connection.
Client_id implies an OpenID Connect connection.
Typically, Angular connections would use OpenID Connect e.g. sample here.
What version of ADFS? If 2019, rather use the MSAL rather than the ADAL sample.
That sample shows the ADFS configuration.
They then need to send you the client_id, redirect_url etc.
This information is not contained in the metadata.
I am trying to figure out correct way to implement JWT auth with Blazor (WASM).
After going through the docs a got an idea on how the built in components work but still the whole picture is not clear to me.
So in my scenario i have an API sever that will be used, the API server can issue JWT tokens and they can be used to authenticate against the endpoints where required.
So right now i am trying to figure out the correct role for each component.
For start we have AuthenticationStateProvider, as i understand this component has the responsibility of obtaining the JWT token either from server or if one stored locally, also it could handle token refresh when required?
Now since i will be using Typed HTTP Clients i will be using IHttpClientFactory, along with that i will have AuthorizationMessageHandler to attach tokens to desired HTTP Client instances.
Things fall apart for me when i am trying to deal with IAccessTokenProvider, as i understand the default implementation will be called once a HTTP Client is created and http request is about to be made.
What is not clear is how this IAccessTokenProvider will obtain the token.
So the question is whether i should create my own implementation of IAccessTokenProvider and if so how it should handle the tokens.
As i said i wont be using any built in authentication providers and will have my own JWT auth system instead.
Thanks.
The first three paragraphs are very clear and correct. This is how you should do that. I can post here some code snippet to demonstrate how it is done in practice...
Things fall apart for me when i am trying to deal with IAccessTokenProvider,
No wonder... The IAccessTokenProvider is not relevant here. The IAccessTokenProvider is a token provider used in the new JWT token authentication system for WebAssembly Blazor App. But if you want to implement the JWT authentication yourself, you must do that as you've described in the first three paragraphs... which I can summarize like this:
When a user makes a first access to a protected web api endpoint and he's not authenticated (or registered), he's redirected to the relevant pages, type his credentials, etc, which you pass to your Web Api end point dedicated to authenticate the user (register if necessary, etc.), after which the action method called produce the JWT token, and send it back to the WebAssembly Blazor App running on the browser. You should store the JWT Token (perhaps in the local store), and retrieve it whenever you perform HTTP calls (Adding the JWT Token to the headers of the request).
The above described process also involve the implementation of the AuthenticationStateProvider object, that is updated with the authentication state, and notifies subscribers, such as the CascadingAuthenticationState, that the authentication state has changed, at the end of which process other components and objects adapt themselves to the new situation... you know, re-rendering, etc.
So, you see, you've received a JWT Token from your Web Api, stored it a local store, read it, and use it. Reading the Jwt Token from your local store and parsing it, to great extent, is something that the IAccessTokenProvider does, but in the new authentication system, and as you do not use this system, the IAccessTokenProvider is not relevant.
What about automatic Token injection in headers of HTTP client, can i or should i still investigate custom AuthorizationMessageHandler or this component would not be usable without IAccessTokenProvider?
You may add your Jwt Token to each HTTP call as demonstrated below:
#code {
Customer[] customers;
protected override async Task OnInitializedAsync()
{
// Read the token from the local storage
var token = await TokenProvider.GetTokenAsync();
customers = await Http.GetFromJsonAsync<Customer[]>(
"api/customers",
new AuthenticationHeaderValue("Bearer", token));
}
}
which is perfectly fine. But of course you can create a custom DelegatingHandler modeled after the AuthorizationMessageHandler or still better the BaseAddressAuthorizationMessageHandler as you're going to use the IHttpClientFactory to provide your HttpClient service. Try first to attempt to use them without any modifications, and if it's not practical just emulate their functionality.
The last things that bothers me is the implementation of obtaining access token and storing it locally.The best approach i can think of so far is to have a global authentication service, this service will provide the functionality of obtaining the token, refreshing it, storing etc. Both IAccessTokenProvider and AuthenticationStateProvider will use it when token is requested plus will be notified whenever authentication state changes like user logs in or out.
Perfect... Note: The AuthenticationStateProvider should be notified of the change in the status of the Jwt Token. As for instance, when you get a new token from your Web Api endpoint, your code should add it to the local store, and then notify the CUSTOM AuthenticationStateProvider of the change. Your code also should notify the AuthenticationStateProvider in case you delete a Jwt Token, so that your user interface will reflect this changes, etc.
Good luck.
Hope this helps...
I'm posting this in the hope of receiving some feedback/advice and information on something I've been struggling with the last few days. To start I'll give a quick breakdown of the project.
There are 2 applications in the solution:
WebAPI resource & authorization server - Uses OWIN (hosted in IIS) and ASP.NET Identity to issue an authentication token on a correct login and then allow requests to the various controllers.
MVC client application - Has no authorization as of yet (until I figure it out) but will make calls to the WebAPI resource server to get all data. These calls will only ever be made from actions of the controllers in the client app, no client side AJAX calls.
The client application doesn't have it's own datasource. All information is stored in a database which the WebAPI service has access to, so essentially if they provide the correct credentials and the client app receives a bearer token I need to deliver a way for the application to see them as authorized.
What's the best way to handle this?
Is it possible to configure OWIN on the client side to use the OAuth
settings of the server? Am I barking up the wrong tree and will I need to just use HTTPClients?
Could I deserialize the bearer token and store it in session, and
then write my own authorization providers to check these on the client side?
My initial concerns are I'm abusing Bearer Tokens and trying to cobble them into a solution which isn't ideal. All examples of external authorization I've found so far usually involve making calls to providers hosted by Google/Facebook/Twitter to check the user is who they say they are, and then moves on to creating a user record in their system. My application can't do this.
In regards to security I was planning to introduce filters which would validate the request has came from the client application by providing an identifier and secret, along with IP validation.
I realize this may be a bit open ended, but I'd appreciate any advice. The scope of the project is that the web service is the only thing to have access to the database. The MVC client application will be hosted on a different server, and the service will only accept requests from said client application.
You don't need to access the data source in your MVC app to validate the bearer token. Basically, you can do it in the following way,
MVC app requests access_token from webapi and passes it to the UI client (let's say a browser).
Browser stores the access_token in a cookie/localstorage and sends them to the MVC app for all subsequent requests.
Create an ActionFilter in the MVC app to validate if the request from the browser has the token supplied in the header. If not, reject the request.
MVC app passes the access_token in the Authorization header to the webapi.
Use HTTPS for all communications (between MVC app <-> Client and MVC app <-> WebAPI)
You can further obfuscate or encrypt the access_token you get from the WebAPI on the MVC app side for additional security but then you will have to send the decrypted version back to the WebAPI.
I realize that my answer is a bit late, but maybe it helps other people:
The bearer token that you get from the API has a list of claims encrypted that only the API can decrypt. I assume you need to have these claims on the MVC application as well so you can restrict resources on the client.
So, what I have done was to first get token. After you get it, you make another request to the API resource api/me/claims to get the list of readable claims on the client. Based on this list you can allow access to resources in your MVC CLient Application using a custom claims based Authorize attribute. Also, you can store the claims in a cookie in the client session. Below is the code for the API controller to get the Claims.
[RoutePrefix("api/me/claims")]
public class ClaimsController : BaseApiController
{
[Authorize]
[Route("")]
public IHttpActionResult GetClaims()
{
var identity = User.Identity as ClaimsIdentity;
var claims = from c in identity.Claims
select new
{
subject = c.Subject.Name,
type = c.Type,
value = c.Value
};
return Ok(claims);
}
}
The idea is to reconstruct the ClaimsIdentity object of the logged User on the Client side and maybe add it to the session.
The token is not enough. You might risk getting a Not Authorized response from the API on a resource that you have made visible for the user in the MVC Client Application. Needles to say that is recommended to use HTTPS for all requests.