Web API authentication using OAuth 2.0 token and Azure Active Directory (Without Authentication Server) - web-services

Is there a way to authenticate the Microsoft or google OAuth token in active directory without using an authentication server?
Here is the scenario:
A client app gets an Microsoft access_token from some external service.
Client app will make a call to some secured web API and pass that access_token along with the request header
If the access_token passed by client is valid then API will provide response to the client.
Is there a way to validate that access_token on API side?
My normal understanding about OAuth 2.0 is there needs to be an authentication server to which both the client and API would talk to as shown in the figure below:
But if the token is provided by some external service, Can we use it to validate our web API. Are there any ways to implement such authentication?

You can learn more about AAD Signing Keys and handling Key Rollover using this page: Signing key rollover in Azure Active Directory
Validation of the token, once you have the signing key, can be done using existing libraries like OWIN. You can also try following instructions like this (although it seems the document isn't 100% complete yet): Manually validating a JWT access token in a web API
This library is also available, but I think OWIN is supposed to have replaced it in general.
Also check out this blog post, which has a pretty great deep dive into token validation.

Related

How OAuth authorization works via API

It is clear how to get a token from Google(or any other OAuth provider). But I do not understand where shoud I do it - server part or client part.
For example: I have a backend on Flask with unified API for Android, iOS and web(js/react) apps.
Where do I need to get a token? On the client (Android for example) part and send it to server or in my Flask app after request from client? Where should I get data from provider? How at all works interaction between client and server while using OAuth?
Would be pleased for some explanations or links on some guides
Your UIs will manage redirecting the user to authenticate - after which the UI is given an access token to call the API with.
The OAuth provider is the entry point for authentication and issues an access token afterwards.
The API uses the access token to identify the user and authorize access to resources.
A good way to understand OAuth is the HTTP messages - my blog post highlights these, and they are largely the same for SPAs and mobile.
There are also some code samples on my blog which you can run, in case useful.

django-rest-framework-social-auth requires a client secret for convert token

I am making an Android application with a Django based backend.
The Django server has a REST API to serve user data which I want to protect. I only want my users to log in via Google (or FB which I'm going to implement in the future).
I am using django-rest-framework-social-auth to implement the authorization in the backend.
So the flow as I understand is like this:
The client (my android application), does the whole Google OAuth2.0
flow and obtains the access token
The the client then wants to
convert the Google access token with one with which it can access my
backend server API endpoints. To do this it calls the convert-token
API endpoint implemented in django-rest-framework-social-auth
Now that it has the API access token, it can include that in the header of all further API calls and receive the private data.
Now my concern is, the django-rest-framework-social-auth convert-token endpoint also needs the client-id and client-secret generated by django-oauth for the application. So I will have to store the client-secret somewhere in my mobile app, which entirely defeats the purpose of authenticating whether the request came from the app or not, because someone can decompile the apk and get the app and make token exchange requests on my app's behalf.
Is there any way around this? Is there a "standard" way to implement this which I don't know?

Facebook Places Search using Client Token

This page claims that you can access the Places Graph functionality without having a logged-in user:
You make your calls using a Client Token (from the client), and an App Access Token (from the server).
The documentation regarding Client Tokens says:
The client token is an identifier that you can embed into native mobile binaries or desktop apps to identify your app. The client token isn't meant to be a secret identifier because it's embedded in apps.
This sounds like exactly what I want--I am trying to build a website that allows users to search for Facebook places. I need to be able to build the list using an AJAX request from the client side.
I can't for the life of me find any documentation on using the Client Token to make such a request.
Please note that I cannot use an App Token because this will be deployed to a website, and Facebook specifically says not to use App Tokens in that context.
I've tried using the Client Token directly as the access_token, but then I get Invalid OAuth access token.
How can I use the Client Token to make a Places Graph API call directly to Facebook's API from the client's browser?
Note: I realize that I could send the request to my own server, then relay that request from my server to Facebook, but that is not an optimal solution for me.
In case anyone is still struggling with this like I was. You just need to use the appId and client token joined with a pipe. So "appId|clientToken".

Django API fronted by Azure API gateway

I have a Django application that currently stores user credentials and performs authorization and authentication. I am in the process of breaking off the front-end into an Angular SPA and converting the backend to a REST API. My Django API will live as an Azure API app protected by Azure API Gateway. I would like to remove the authentication piece from Django and allow users to sign in using OpenID Connect through either Google or Microsoft Account. What I would like to happen is this:
When a user visits the site, assuming they have never registered with my app, they will have the option to sign in with their Google account or Microsoft Account. If the user decides to sign in using their Google or Microsoft account, (this is where I'm confused and why i'm posting here ... ) I think what happens is the API Gateway performs the authentication, generates a JSON Web Token (JWT), and sends that token back to the Django API. Django receives the JWT, decrypts it, and checks to see if there is a user account matching the email address in the JWT. If there is not a user account, Django will add a user to the user accounts table (not storing a password). If there is a user matching that email address, then Django allows the user in.
All that said, I guess my question(s) are:
Should I do the authentication at the API Management Gateway or should I do it at the Azure Web API?
Can I use Django's built-in authentication system to do what I want or is that not needed?
Am I over-complicating all of this? Is there an easier way to do this? All this seems like a lot of work.
Is OpenID Connect what I should be using (instead of Oauth2)? I have no experience with either.
Azure API Management does not actually provide any kind of JWT issuing mechanism, so you'll have to implement that yourself. The end points for doing that may or may not be exposed via API management.
What possibly gets you confused is the fact that the APIm Portal supports various indentity providers, like Twitter or Google, to sign up for the API. But these are not your application users, these are for the API Portal Users.
What you can do with the APIm Gateway is to validate subsequent calls to your backend API that the supplied JWT token is valid (using the <validate-jwt> policy).

Generate an OAuth2 token in a view

Let's say I have an AngularJS application that consumes the REST API of a Django application.
The Django application has got a built-in OAuth2 provider that can be called to retrieve an access token and use the protected endpoints of the API. This provider is using django-oauth-toolkit.
Let's assume there is a registered client with "password" grant type, so that the end users only need to provide their credentials in the front-end in order to get an access token from the back-end.
At some point we want to add some support for social networks login and we decide to use python-social-auth (PSA) to that end. Here is the workflow I want to achieve:
The user logs in on Facebook from the front-end (via the Facebook SDK) and we get an access token back from the OAuth2 provider of Facebook.
We send the Facebook token to an endpoint of our REST API. This endpoint uses the Facebook token and django-social-auth to authenticate the user in our Django application (basically matching a Facebook account to a standard account within the app).
If the authentication succeeds, the API endpoint requests an access token from the OAuth2 provider for this newly authenticated user.
The Django access token is sent back to the front-end and can be used to access the REST API in exactly the same way that a regular user (i.e. logged in with his credentials) would do.
Now my problem is: how do I achieve step 3? I first thought I would register a separate OAuth2 client with Client Credentials Grant but then the generated token is not user-specific so it does not make sense. Another option is to use the TokenAuthentication from DRF but that would add too much complexity to my project. I already have an OAuth server and I don't want to set up a second token provider to circumvent my problem, unless this is the only solution.
I think my understanding of PSA and django-oauth-toolkit is not deep enough to find the best way of reaching my goal, but there must be a way. Help!
I managed to get something working using urllib2. I can't speak towards whether or not this is good practice, but I can successfully generate an OAuth2 token within a view.
Normally when I'd generate an access token with cURL, it'd look like this:
curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/
So we're tasked with making urllib2 accomplish this. After playing around for some bit, it is fairly straightforward.
import urllib, urlib2, base64, json
# Housekeeping
token_url = 'http://localhost:8000/auth/token/'
data = urllib.urlencode({'grant_type':'password', 'username':<username>, 'password':<password>})
authentication = base64.b64encode('%s:%s' % (<client_id>, <client_secret>))
# Down to Business
request = urllib2.Request(token_url, data)
request.add_header("Authorization", "Basic %s" % authentication)
access_credentials = urllib2.urlopen(request)
json_credentials = json.load(access_credentials)
I reiterate, I do not know if this is in bad practice and I have not looked into whether or not this causes any issues with Django. AFAIK this will do this trick (as it did for me).