Authentication-Authorization issue when dealing with WebAPI - asp.net-mvc

I'm re-developing an app as a web app (the "previous" iteration was in VB6) to run on azure. One requirement is that we only use facebook/google authentication (OAuth 2.0). Another business requirement lead me to break my project into the following schema:
1 Project for the WebAPI 2.0
1 Project for Controllers
1 for Data Access (typical layer pattern)
N Projects for MVC 5 front-end
The idea is that the MVC projects will only consume the WebAPI via javascript/json! The N MVC projects will contain just the GET implementation for the pages. No models or others actions (post for example). In other words the MVC projects are completally disconnectd from the other projects and should have no intelligence what-so-ever!
This is the selected way because of (bitchy clients and) limited time constraints.
Anyway, as you can notice the "core" (WebAPI + controllers + DA) is shared. The core is in fact a multi-tenant service. (but remember the disconnected facet!)
My problem here is: How do I handle Authorization? What/how should treat the passing of the claims between the MVC projects and the WebAPI? Im lost here. After some thought, I came to the conclusion that I need to make the WebAPI project act as a proxy here, something like:
Random users lands on www.myClientWebsite.com/Register
Chooses a login provider
The MVC project redirects the user signaling facebook to return to www.myWebAPI.com/Register
I intercept the claim and redirect the user to the original www.myClientWebsite.com/LoginComplete or something...
Am I getting it wrong?

You have to use OAuth 2 for authentication and authorization purpose in this scenario. Yes, you should be making the authentication at the MVC level and then use tokens to keep the security intact for rest calls.
Here your MVC application should get a Bearer token from the identity provider like google and then hide it some where on the form. Then for every jquery request you make to web api, you have to send this bearer token in the request.
[Update]
This is considered kind of hack and I do not encourage it. And this works only if both the systems are in same domain.
[\Update]
If both MVC and Web API are on different domains, then you can think of using Azure ACS Service Identity to build the trust between domains. Then pass the bearer token of User claims in the payload of the request.
[Update]
This is much more better way to handle this but must be accompanied with proper token revocation and https security.
[\Update]

Related

Can I use OIDC Hybrid Flow While Serving Angular SPA from ASP.NET Core MVC Project?

I've got 2 different .NET Core 2.2 MVC projects. I'm using IdentityServer4 for the token server, Azure B2C for the identity store.
The 1st MVC app is a normal MVC application, and I've got it working perfectly with the OIDC Hybrid flow.
The 2nd MVC app is an Angular 7 cli app, which serves up the index.html and houses the API that the app will be calling. The angular app will not call any other APIs directly (gateway pattern).
My questions are about the 2nd app - I'm trying to figure out the best way to set up the Angular app for security.
My understanding is: OIDC Implicit flow exposes exposes the access token on the browser. OIDC Hybrid flow does not expose the access token (at least when hitting the same web server - no CORS), because the web server (client) uses the back channel to obtain the access token, via the authorization code, and its never exposed to the browser.
QUESTION #1: Is my understanding of Implicit vs. Hybrid correct?
If my understanding is correct, I'd think the best way to go would be Hybrid flow even for the Angular app, but most samples I've seen for using OIDC with Angular involve the Implicit flow, and don't take advantage of the authorization code / backchannel. Avoiding having an access token on the browser seems like a big deal, like a worthy goal, but wondering why it doesn't seem to be done?
QUESTION #2: I'm serving up my Angular index.html from my MVC server - why can't I just use Hybrid flow to protect the index.html page, and keep the token on the backchannel?
Something tells me my understanding of all this isn't quite complete...
Your understanding is correct. You can protect your index.html. The only problem you will face that way is that it's not the default configuration for today. With your requirements, most likely you don't need any of oidc client libs at all, you can protect your (only) API with a (same-site, http-only) cookie (not a bearer token) and in your Angular guards just ensure that you are still logged in to your back (if not, redirect through a local MVC resource to involve server-side code into login procedure).
See this question, especially the comments and link below for further reference.

SPA calling a WebAPI calling a WebAPI

I am building a SPA (javascript) which will call WebAPI A (.net MVC API) and which in turn will call (server side) WebAPI B (.net MVC API).
All three entities are protected by ADFS4 (OAuth2). In my workflow I want WebAPI A to call WebAPI B on behalf of the user who has logged into the SPA.
In reading the various documentation by Microsoft I found that the scenario described in the following article applies best to my case:
https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/ad-fs-on-behalf-of-authentication-in-windows-server
The article assumes that the client application can perform the authorization grand flow. Nevertheless in my case I am dealing with a SPA which should be using the implicit flow of OAuth2. In addition even if I wanted to use the authorization grand flow I would still need to do a POST on the token endpoint of ADFS from the SPA which is not possible as ADFS4 does not offer a way to add CORS headers. I could of course deploy a proxy in front of it and add the headers... I have not explored this option yet.
I found a solution to make this work but it seems more like a hack to me; The SPA during login requests two tokens (1 for WebAPI A and 1 for WebAPI B) from ADFS4. It passes both tokens to the WebAPI A which knows that the 2nd token is for accessing WebAPI B.
Does this solution seem correct? Should I be doing something differently?
Thank you!
PS:
1) SPA cannot accesss directly WebAPI B as it is accessible only internally.
2) Assume I have total control over development on all three entities.
it's not a good idea to use the authorization code flow for SPA application, because you have to really keep the secret key that can generate access_token, which is not secure in that case.
i suggest that you use the implicit flow for you spa application and between your servers use the authorization code flow, this way you are sure about security

Web API Security ( Authentication )

Background:
I've implemented a Web-API (.NET), now I need to do the most important thing,
Secure it.
As I investigate this topic I understand that the common way is the Bearer Token.
Now we getting to my problem.
My Problem
On one side:
Every article I saw (that explains the concept and the way to implement it over .NET) starts from a project with a Web API template that holds MVC and Web API and in the authentication field choose one option from Individual / Organizational / Windows .
On the other side:
I don't need a MVC project, I need only Web API (without any GUI) that the reason I choose the empty project and check the Web API checkbox, in that way I cant choose an authentication type, I forced to start with no authentication.
Questions:
1.Do I bound to use MVC to get authentication ? if not how can I do it from pure Web API project ?
2.Maybe I will create an Authentication Server (that only generates tokens) from that Web API template (with the possibility of choosing authentication type) ? (and use the token on the real Web API)
3.There is any benefits of implement the Authentication Server on a different project and on different server ? (Kerberos style )
P.S I want to use an out of the box solution because the security aspect is the most important one (to my opinion) and should be flawless.
I wrote a blog on this topic called 'Securing and securely calling Web API and [Authorize]': http://blogs.msdn.com/b/martinkearn/archive/2015/03/25/securing-and-working-securely-with-web-api.aspx. I think if you read this, you'll have all your answers.
The Web API template does include MVC by default so that you get the automated docs feature (which is a great feature to have). However the authentication part is related to a core ASP.net feature, not specific to MVC or Web API. You'll need to enable one of the authentication options to secure your API using .net's built in security features.
If you do not want the MVC project that comes with Web API, just delete it after the project has been created. It is contained within the 'areas' folder. If you delete that folder, you'll be running on pure web api.
To answer your specific questions:
1) No you do not need an MVC project to secure an API project. You can use the [Authorize] attribute on your API controllers and actions.
2) an authentication server gets created by default with the web api template. You can access it and get tokens via http:///Token
3) No, you need to use the api itself to serve valid tokens for secured controller/action requests
Hope that helps. If not, then please be a bit more specific with your questions.

Azure ACS + MVC + WCF

I got a MVC web application that authorizes users through Azure ACS. Now I want my web application to make calls to my WCF services. Since these services can be called by other applications I want them to be secured through ACS also. I'm at a loss on how to set this up. Can I reuse the security tokens in my WCF service calls somehow?
Formally you can't because these are 2 different (autonomous) "apps". Tokens are issued for a specific app (or "Relying Party"). Your website should request a second token for the web service. You have 2 options:
1- Simply get a token under a service identity (that is the identity the web site is assuming) and attach it to your calls to the web service. WCF bindings support this out of the box (albeit complex, as any WCF configuration),.
2- Get a token for WCF "on behalf" of the original user. This is a delegation scenario, in which the identity of the original caller to the web app is transferred to the service.
The first option is rather simple (putting aside the WCF specifics). The second option is more complex one and not supported in ACS (as far as I know), because it requires a special endpoint that understands and issues ActAs tokens.
You could use the same token for both the web site and the service if you own both and are "the same app". This is a pragmatic shortcut and not a pure implementation, and might have other implications (e.g. the same app in ACS, the WCF can't easily distinguish that it is being called from your website or external parties, etc).
In that case, the MVC app must keep the token that was sent to it. There's a setting for that (bootstraptoken=true). The WIF API in .NET 4.5 changed a little bit, so there might be something else.

Calling a WCF service that uses ACS from a MVC site

I have a MVC website that uses ACS as an authentication provider.
The authentication process works well.
I want to call a WCF service that requires authentication and I want to pass an RST token but I don't know how to create it
The key question is what identity is the WCF service expecting. If you can use an identity for the entire MVC site (a.k.a. "Trusted Subsystem"), then it is business as usual: you would need to get a token from an identity provider that the WCF trusts and that's it. ACS could be one, but it could be something entirely different too. It really depends on who owns the WCF service.
If, on the other hand, you want to flow to the WCF service the original user identity (that is the caller of the MVC site), then you are in a delegation scenario. This is possible, but it's often complex. Search for "Act As" (here's an article that talks a little bit about it: http://msdn.microsoft.com/en-us/library/ee517268.aspx).
In a nutshell, the MVC app would request a new token to the STS using as input the original token the user submited, with a special condition (the "Act As"). This condition signals the STS of the delegation.
As I said, this is a farily complex setup. Also (last I heard) ACS doesn't support "Act As" requests.

Resources