I know SignalR is not available for ASP.NET Core 1.1 and in preview for 2.0. Meantime I need to work around this limitation.
The application I'm building is an ASP.NET Core 1.1 MVC application. One small but important feature in this application is case management. The view needs to be updated with new incoming cases for that specific user.
My SignalR 2 hub runs in a separate ASP.NET 4.* application.
I was hoping as this is all 1-way that I could easily use the SignalR JavaScript client instead of the .NET client and Bob is your uncle.
The problem however is AuthN/AuthZ for which I'm using Azure AD B2C (oauth2)
Within the MVC app I use standard cookie authorization, but the pattern I'm using for the backend API's is that I use my MVC code to wrap the access token in a bearer tokens and sent that to the backend API where I use jwt bearer authorization. Therefore my clientside JavaScript never sees the access token, just the cookies that the MVC app uses between View and Controller.
The problem now is that if I want to connect to the Hub using JavaScript I have nothing to sent to the Hub to prove my identity as the jwt token only exists in the MVC host, and the cookies are HTTP Only so inaccessible.
Any ideas or alternatives?
Thanks!
Ok I found it! I can use the following method to pass along the cookie from my MVC app:
Follow instructions in https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/compatibility/cookie-sharing to setup cookie sharing
Use the withCredentials=true on XMLHttpRequest.withCredentials through the start method on the hubConnection in SignalR
conn.start({ withCredentials: true }).done(function () {
hub.invoke('recordHit');
});
Setup CORS in the Hub project.
easy! Works like a charm
Related
I am developing an angular +.net core web app(not to be confused with .net core MVC web app).
My UI client uses angular, my backend web api's use .net core 6. I am using external IDP to authenticate my angular app for that I am using AddOpenIdConnect. All though I am not using MVC for my other APIs(using web api type controller) but I pulled in couple of MVC controller(Home and Account) from the sample app present in external IDP's sample project(as I could not find a way how to achieve it with my APIs).
On login button press in my angular app I call this method of Account controller which redirects me to external IDP. After successful authentication I am being redirected to my angular app's landing page (http://localhost:4200/admin) which solves my purpose as far as SSO is concerned. Also in OnTokenValidated event I am getting the access token as well.
Now the problem I have with this approach is:
How can I return this token to my angular app(which is an independent SPA) so that it can be used as authguard for the angular app and for safe guarding other api end points?
I am thinking of making another end point which angular app would call after successful redirection which would return the claims and access token to UI. I tried fetching it from HTTPContext in the end point that I made but it is coming out to be null and User.IsAuthenticated as false.
How can I secure my web api end points with this same access token? I am thinking of using the access token returned to UI after redirection for authentication and then it can be sent back to backend apis in header for authentication. How can I achieve that?
All the example and sample code(even on IDP's website) use .net core MVC. Did I make a mistake by making it a web api project?
I am hoping someone can advise me on this please.
I have been following a modified form of this tutorial Getting started with thinktecture Identity server to try to setup a site with OpenId Connect authentication.
I have this set up:
An Asp.NET MVC project acting as the Identity Server
An Asp.NET MVC project acting as the secured website
This above setup is working perfectly. When someone attempts to access a controller with the [Authorise] attribute in the secured website, they are redirected to the Identity server to login, and then redirected back to the secured website after successful login.
I would now like to add a web api into the mix. I have created a WebApi project, but unlike in the tutorial where it is called server side using a 'service account', I would like to call it client side (JQuery) from the secured website with the identity of the currently logged in user.
I understand that I need to use a bearer token in the authentication header.
My question is: How do I get the bearer token for the currently logged in user on the client side so I can set the header? (The user is already logged in.)
Many thanks in advance for your help
If you are using .Net Framework 4.5.1 in your Identity Server app, you may already have the TokenEndpointPath defined as "/Token". Look in your Startup.Auth.cs file in the App_Start folder.
A calling client may retrieve a bearer Token from the /Token endpoint by POST-ing a valid username / password to the endpoint. I created a simple codepen to experiment with my own ASP.NET Web Api 2 project using the new Windows Identity Foundation infrastructure. You might find something useful in it:
http://codepen.io/randomfactor/pen/bNpBoP?editors=101
# THIS IS CoffeeScript (because we are not barbarians)
# start by trying to get an access token
$.ajax {
type: 'POST'
url: "#{appUrl}/Token"
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
data: {
grant_type: 'password'
username: $('#login-name').val()
password: $('#password').val()
}
}
.then (data) ->
Be warned that, by definition, the codepen is making a Cross Origin Resource Sharing request to your Identity Server project. To make that work, you will need to modify your Identity Server project to support CORS as described in the comments on the codepen.
If you are willing to combine your Identity Server with the secured website and the Web Api project under .Net 4.5.1 (highly recommended!), it will simplify some things and you won't need the CORS modifications.
I guess you can inject them into a DOM in _Layout.cshtml. Better by initializing some OidcClient and AJAX before send.
What do you think, #PinpointTownes?
I have created a new web api project with individual user account authentication.
I followed this post and everything worked as expected
http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
Now, I have a token end point
localhost:54452/Token
Lets, say I create new asp.net mvc application. I want to use this token end point for authentication. How do I tell my controllers to use this token end point? How do I tell my controllers to pass the bearer access token on each request or how does these two work together.
asp.net mvc and asp.net web api are two different projects with different port numbers
Thanks,
Syed
I would create a wrapper class that uses HttpClient to issue HTTP requests to the Web API. Then use this wrapper class when you're communicating with the Web API. It will then handle adding the token to the HTTP request header.
I am working on an existing project which is on dotnet framework 3.5 . I want to implement Web API and want to call this webAPI from javascript by using jquery.
I want to apply basic authentication and also want to use authorize the HTTP methods of WebAPI.
Before using webAPI we are using simple authentication process by using Session variables in our application and checking the authentication and authorization process in page load method it self in the page.
Please suggest some better idea to implement the web API authentication in my application.
A quick google brings up lots of results.
Http Authentication using filters
Http Authentication using message handlers
Or you can checkout the webapicontrib which has examples of Http Basic Auth and more. You will possibly run into cors issues calling the api with javascript, webapicontrib has an example of a cors handler too if you need it.
Take a look at the Thinktecture identity library. It's so far the most complete one for ASP.NET projects, http://thinktecture.github.com/Thinktecture.IdentityModel.45/
I am trying to do something like this:
I have a MVC4 Web App and a Web-API service (hosted on two separate roles in azure)
Another role runs CustomSTS1.
The MVC Web App trusts the CustomSTS1
Now the customer logs into the site he is redirected to the STS login page.
Once logged in, he is redirected back to the MVC Web Site.
From this web site, the customer performs actions, which in turn invoke the web-API Service.
I have the SAML token in the web app, which I pass to the WebAPI service.
Now when I try to validate the SAML token at the Web API side, I get a
Message=ID1032: At least one 'audienceUri' must be specified in the SamlSecurityTokenRequirement when the AudienceUriMode is set to 'Always' or 'BearerKeyOnly'. Either add the valid URI values to the AudienceUris property of SamlSecurityTokenRequirement, or turn off checking by specifying an AudienceUriMode of 'Never' on the SamlSecurityTokenRequirement.
This is without the Web API service trusting the CustomSTS1
Once I setup the trust,
I am always given a HTTP 401: UNAUTHORIZED, whenever I try to make a HTTP Get request to the WEB API Service.
Now, My Question is, (I know that my current approach is definitely wrong)
How do I setup the Trust relationship with the CustomSTS1, such that the WebAPI service is able to do an ActAS on behalf of the user logged into the MVC site?
OR
Is this architecture wrong?
And is there another way to achieve this?
That approach is wrong conceptually. The MVC application should negotiate a new token for the Web API in the STS using ActAs. That's how it traditionally works for SOAP Services. However, Web APIs are moving away from SAML as it is a complex format that relies on different WS-* specs. OAuth 2.0 is becoming the standard in that area if you want to support SSO at that level.
Another approach is to establish an implicit trust between the MVC app and the Web API, so all the calls to the Web API from the MVC app are done through a more standard Http auth mechanism like Basic Auth using an specific set of credentials that only the MVC app knows. The info about the logged user in the MVC app is passed as additional information.
Regards,
Pablo.