Web API 2: Authentication and authorization with third-party access tokens generated in the browser - asp.net-web-api2

I am struggling with understanding how to implement the following in Web API 2's OWIN pipeline.
I am building an application that will allow users to log in with several third-party identity providers such as Facebook, Twitter, LinkedIn, etc. However, I want the authentication step to be performed entirely client-side. For example, Facebook provides developers a snippet of markup and JavaScript that perform the authentication within the browser, resulting in a Facebook access token--all without any calls to my API.
The Web API templates that ship with Visual Studio 2013 all seem to assume that the API itself is in charge of the authentication flow. I have successfully gotten this style of authentication working, but in my opinion it is not the responsibility of the API to perform this work.
Here is the approach I have been trying to implement (so far unsuccessfully):
Provide endpoints like /authenticate/facebook that accept the appropriate access token and return a JWT with "decoded" claims if the access token is valid. This JWT would have similar claims regardless of the third-party identity provider. For Facebook, I think this involves a call to Graph API's /me endpoint.
Store the JWT in the browser's localStorage for subsequent API calls
Send the JWT in the Authorize header for each API call
Avoid cookies if at all possible
My questions:
Is this an appropriate way to handle third-party authorization?
Should the JWT's expiration match the third-party access token's? I assume yes, but I want to be aware of any caveats here.
Where and how do I store the third-party access tokens for use on subsequent API calls? Do I include them with the JWT?
Is there a template I can use out-of-the-box, or perhaps an online resource that implements authentication and authorization in this way? I don't understand how to use Web API's many classes and features to implement this.

I have this mostly figured out now. I believe my architecture choice is the correct one after much research, specifically into the so-called "assertion flow." I am using Thinktecture's Identity Server 3 project to act as my STS. I am using a custom implementation of ICustomGrantValidator to perform the validation of the Facebook access token and conversion to claims.

Related

is OAuth 2.0 appropriate for my use-case?

I am building a restful API that allows users to access and manage their own resources programmatically (via CURL/HTTP) instead of using the dashboard we provide.
I have my own authorization server and resource servers so there is no 3rd party involved. I am torn between using OAuth 2.0 and simple API Keys. OAuth 2.0 seems like an overkill, yet I don't want to release a public API then change the authorization method in the future.
Is it possible to build a hybrid solution where users can log-in to the dashboard, generate a "refresh-token", specify the scope, then copy this refresh-token and use it in their own code to call the /token endpoint and get an access token?
This would be similar to OAuth 2.0 except that the authorization step is done directly by the authenticated user on the 1st party dashboard. Is this a legitimate solution? Do you have any other recommendations?
OAuth2 is to outsource user/password/MFA management, integration with social logins. You seem to manage users in your dashboard already. On that basis, issuing a manual access token as you described works, provided you sign it and the verify signature in the api/resource servers.

System to system integration and token validation

We are trying to set up a scheduled job based on NodeJS which will call an API via an API gateway. The API calls another API. There is no user or browser involved. The call must be authenticated and have a valid OAuth token from our IdP. How should it look like to have a more secure approach?
How the flow should look like? Which one the API Gateway or the second API should validate the token? or both? Thanks
A key point is that JWT access token validation is designed to scale. In older architectures it was common to use perimeter security (eg API gateway validates token) but this is no longer recommended.
Instead validate the JWT in each API using a library. Here is some example code and for other technologies see Curity API Guides.
Here are a couple of related articles if you are interested in API security trends:
Zero Trust Architecture
Phantom Token Pattern
Finally, this article discusses that JWTs can often be forwarded between microservices, to keep your code simple.

Integration of frontend and resource server using okta authentication and client credentials API authentication

We have an application that has frontend UI(Which is a web application) which communicates with a resource server. Our frontend will be using some APIs from a resource server to get data.
I am planning to add frontend to Okta and provide access to okta registered users.
In the resource server, we have some APIs that we want to expose to our customers to integrate in their system(Programmatically). To use our APIs, we have to provide client credentials(client ID/secret) to them. Using clientId/Secret, they will get access_token and will use that in a subsequent request. We can display this clientId/Secret via frontend UI once the user logs in to it via Okta.
How should I authenticate requests to the resource server from the frontend? And how do I authenticate requests to resource server via customer using clientId/Secret? Should I use one or two different tokens for this purpose?
Does Okta provides per-user client Id/secret that user(customer) can use to get access_token and send it to access resource server and resource server validate token against Okta.
I just did something very similar. You can read about my experience here: How to pass/verify Open ID token between .net core web app and web api?
I don't know what application framework you are using (.net, node, etc), but if you're using .NET the steps are to (a) install the middleware in your web app, (b) install the middleware in your api app, and (c) make sure calls from your web app to the api app pass the id_token.
If you, in addition to that, need to secure it for external users - it should work the same way. The only difference is they will manually call the /authorize endpoint to get their token - but the middleware should take care of the token verification for you in both cases.
Note I did experience one odd thing which is that I needed to pass the id_token and not the access_token. It is also worth mentioning that the claims were interpreted differently in the app and the api (in that the name of the claims for say, userid, were different between them - the data was still the same).
You will have to use 2 different access tokens. There are 2 different flows going on here:
Web UI to API
Business partner system to API
Technically this means:
Authorization Code Flow (PKCE)
Client Credentials Flow
And in terms of tokens it means:
In the first case there is an end user represented in access tokens (the 'sub' claim)
In the second case there is only a Client Id claim in access tokens
I can advise on token validation techniques if needed - let me know.
To me though this feels like an architectural question - in particular around applying authorization after identifying the caller and versioning / upgrades.
Based on my experience I tend to prefer the following architecture these days, based on 2 levels of APIs: eg with these ones exposed to the internet:
User Experience API serves the UI
Partner API deals with B2B
And both entry point APIs call the same core services which are internal. Might be worth discussing with your stakeholders ..

Using IdentityServer vs creating custom JWT based authentication

Authentication is a bit over the top for me.
My understanding is:
Client performs the login
API or authentication server responds with a token
Client calls API (includes a header which holds the token)
API checks if the token is valid and if valid responds with a resource
I checked several options:
IdentityServer4
Has the advantage to easily implement 3rd party authentication like Facebook. You can easily use the ASP.NET Core identities to authorize your API based on roles.
Custom (simple) JWT authentication
Reference: ASP.NET Core Token Authentication Guide
With this approach, you have to make your own identity user and fetch it from a database.
Cookie authentication
The client holds the token in a cookie when sending a request you have to send it too.
My front-end is written in JS and back-end is ASP.NET Core, so it's CORS.
I don't know what should I use and why? Why do many recommend to use IdentityServer4; isn't the simple custom authentication enough?
(I have problems with the IdentityUser properties and the "hidden" database checks)
The problem with authentication is that it may be simple to write a few lines of code that accomplish the end goal of authenticating your users, but it's really complex to do so in a way that you won't regret it later; aka my application got owned.
One of the steps to take to try to prevent that from happening is don't try to reinvent the wheel and stick to using current standards. However, even with standards, you need to implement them accordingly and that is why you probably see recommendations like the one you mentioned. I would actually make the same type of recommendation my self, delegate as much as you can to third-party libraries like IdentityServer4 or cloud services like Auth0. (you should know I work at Auth0, so you can consider me biased; however, for a non-biased recommendation you can check ThoughtWorks Technology Radar).
Also, if you store tokens in cookies, although the storage and transmission of the token happen differently this is still a token based-authentication system; for more on the possible implications of choosing a client-side token storage approach check where to save a JWT in a browser-based application.
In relation to CORS, you did not make that explicit, so I thought it may be worthwhile to mention it. You only need to actually worry about CORS if you deploy your front-end and back-end in separate domains because even if development happens in isolation if they share a domain CORS is one less thing you need to worry about.
Conclusion
For a front-end browser-based application talking with a REST API, the most common approach is to go with token-based authentication that relies on OAuth 2.0 protocol to perform the actual issuance of the tokens. Additionally, you should aim to delegate token issuance to a third-party (IdentityServer4 or other) so that you don't need to implement or maintain that part of the system and only need to consume/validate the generated tokens.

How to use OAuth2 within django-rest-framework?

I've been trying to integrate OAuth2 authentication in my drf application. Given I don't yet need a front-end for my app, I was using the browsable API. DRF and the OAuth2 provider package are supposed to work together without much configuration, as explained in the tutorial.
I should mention that all the steps from the tutorial are working (so I can access the app from the command line) but when I try to do it from the browsable API, I don't see any request for an access token or anything like that.
I think that DRF does not actually provide the flow for the front-end part of authentication by OAuth2, but I was just wondering if someone managed to make it work (because for now I am using SessionAuthentication).
Thanks.
OAuth2, unlike basic authentication and cookie-based authentication, does not easily work within the browser. When authenticating requests, it relies on the Authorization header being present (with the OAuth type) and there is no way using a browser to easily fill that in.
Session authentication relies on cookies, which most browsers easily support, and is recommended for interacting with APIs that are on the same domain as the front end.
Basic authentication also relies on the Authorization header, but uses the Basic type which is supported by most browsers.