Authenticate to Azure Function from within App - azure

I'm using Facebook Authentication for my Azure Function App, it works fine if I navigate to a function within the browser. I would like to invoke my functions from within an app but an unsure how to perform the authentication.
At current I am attempting to use the Facebook Client, this returns me an access_token that I am then forwarding to the ".auth/login/facebook/callback" function within my function app. Unfortunately that's as far as I can get, doing this via a GET returns HTML with JavaScript in, and doing it via a POST redirects back to Facebook.
What I really need is the cookie created by the azure function, AppServiceAuthSession, I believe I can then use this to call the functions.
Edit: I don't think i can just use the cookie, like I said above so I need to authenticate properly.
Nick.

I was able to get the tokens passed along to the function app while using the Facebook Javascript SDK (I wasn't having any luck with the C# one) -- maybe this will get you moving in the right direction.
The client:
Performs the login to Facebook, which returns an accessToken.
Client needs to exchange this accessToken for an 'App Service Token'. It does this by making a POST to https://{app}.azurewebsites.net/.auth/login/facebook with the content { "access_token" : "{token from Facebook}" }. This will return back an authenticationToken.
Use that authenticationToken in a header named x-zumo-auth. Make all requests to your function app using that header.
From within your function app, you should then have the current Principal set to that logged in user.

Related

Getting OIDC username after authorization

My goal is to tell if a user is authenticated, and get their name and email. So far, I can only do the first.
My server app is a NodeJS/Express router. The OIDC server is provided by my company, I believe is compliant, but not under my control. I can do an "Authorization code flow": response_type="code". My Node app eventually responds to the callback route and I can get the "code" and "grant_id" query string values. Other than knowing they exist and presuming that means the user is authorized, I have no idea what I can do with those values. It appears that the only scope that works is "openid".
If I can get the access_code, I can call the UserInfo service and get these values.
My other choice is to do an implicit call. Unfortuantely, the OIDC service it provides the "access_code" and other values after a hash mark on the callback. I believe the flow to be like this:
User makes call to Node app. Detects a lack of authentication, issues redirect to SSO service implicit authorization
User's browser follows redirect to SSO service implicit authorization. User fills it out and is successfully authenticated.
W3 returns a redirect to the provided callback URL.
User needs to cooperate with the app, somehow parse the query string parameters to get the access token and pass this back to the Node application.
The browser calls the provided Node callback application, but without the necessary access token.
I think I could make a proxy server to force OIDC to give my node server the request, just so I can get the access_token. It seems like a very convoluted way to do this, so I have to think there's some simpler way.
Again, all I want is to know the user is authorized to use the app, and what their name and email is. It should not be this hard.
You can use the ID-token to get the details about the user.
It is also important that your identity provider is all about authentication. Final authorization checks should be done in the client, by examining the scopes/claims in the token.

Server-side authentication using Google accounts in a Chrome extension

I have a Web application that currently uses OAuth2 to authenticate users using their Google accounts. The flow is quite standard: the user logs in to Google, the web app gets a callback, retrieves the user identity and stores it in the session.
Now I need to create an accompanying Chrome extension. This extension needs to access the web app underneath, so it needs to authenticate against this app. I configured my extension using the official documentation, but during experiments, I realized this is not what I need. Since it uses the OAuth2 implicit flow, it doesn't return a token that could be validated on the server side. This flow is suitable only for using Google APIs on the client side, which is not my use case. This documentation (and pretty much everything else I found on the Web) focuses on two possible cases:
We want to access Google APIs on the extension side (chrome.identity.getAuthToken()).
We want to authenticate using an alternative OAuth2 service (chrome.identity.launchWebAuthFlow()).
However, in my case, I'd like to authenticate users using Google accounts, but process the token on the server side of my Web app. I could use option 2 here, but it just doesn't "feel right" to me to create my own "non-Google authentication service" that is just a wrapper over Google authentication service, only to be able to authenticate on the server side.
Is option 2 really the only way to go, or is there any simpler way?
I also saw someone recommending using the tokeninfo endpoint to validate the token, but I find it hard to make sure that this is indeed an "official" and secure way of doing this.
To retrieve an access token that you can use on both parts of your app, the extension and the server, you should request a Google Cross-Client Access Token. This allows you to register your two apps (two client IDs) in a single project and share an access token.
This is described and discussed by Google here:
Docs: Google Identity Platform: Cross-client Identity
Video: Google Drive SDK: Cross-client authorization
The rough steps are:
You will need two clientIds, one for your extension and another for your server app
Add both clientIds to a single project
Retrieve the cross-client access token from your extension
Send it to your server via HTTPS
To do this in Chrome, it looks like you would call chrome.identity.getAuthToken() with a callback function that sends the token to your web app.
The reference says the following on chrome.identity.getAuthToken():
chrome.identity.getAuthToken(object details, function callback)
Gets an OAuth2 access token using the client ID and scopes specified in the oauth2 section of manifest.json.
and that it can take a callback function as specified as:
Called with an OAuth2 access token as specified by the manifest, or undefined if there was an error.
If you specify the callback parameter, it should be a function that looks like this:
function(string token) {...};
Ref: method-getAuthToken

Getting Google User ID in Node.js in Firebase Functions for Assistant App

I'm getting started with Google Cloud Platform.
I'm developing an Android App that will collect information and store it in a Firebase App. The idea is that a Google Assistant function can query this information and read it back- eg
OK Google, Talk To Simons App, Tell me the last time XYZ was done
The problem I've got however, is to get this being multi user.
I've got the Android App collecting data and putting it into the cloud. I'm using the FirebaseUser and using getUid() in the Android app to get a unique id which is a 28 character string like uVHkia8RRgWD8GGPVvW4AUDUK2.
I've setup Actions on Google, got it hooked into API.AI with Web Fulfilment and got Node.js working in firebase functions.
Unfortunately, the UserID I get back looks more like:HTge48H0CF2FC5jJQCigFBc-UCQ
The problem is that this UserID is not the same as the UserUID I got from Filebase User.
Im using
let ApiAiApp = require('actions-on-google').ApiAiApp;
const app = new ApiAiApp({request: request, response: response});
and
const userId = app.getUser().userId;
What am I missing? I see references to OAuth2, Account Linking etc. I'm not entirely sure what to do at this point. All I need to do at the moment, is get the User UID like I get from FirebaseUser.getUID() in order to look the data up in the Firebase Database.
I think the rest should be straight forward.
There's loads of documentation on linking to Firebase from the Assistant, but very little on actually authenticating. So far I've not setup an flows, like Authorization Code Flows, Implicit Flows, or set a username/password against API.AI and the Fulfilment option. Quite frankly Im not sure what needs to go where at this point.
The user provided by app.getUser().userId is designed as a persistent anonymous identifier. It is roughly the equivalent of a cookie that one sets in a web server - you can use it to determine if you've seen this user before, and what else they've done in your Action, but it does not inheriently relate to any outside account.
Unfortunately, the best solution you have at this point is to use Account Linking which requires you to setup an OAuth2 server. As part of this setup, you will need to create three components:
A login web page for your service. You'll provide the URL for this page to Google as part of Account Linking. When the user accesses your Action, and your action indicates they need to log in, they'll be redirected to this URL on their mobile device. On this page the user will log in - once logged in, you now know their Firebase ID and will create an auth code for this user. You'll then redirect them back to a different URL and pass this auth code (along with some other info) as a parameter.
A token exchange endpoint. Google will call this URL with the auth code above. You'll verify this code, determine who the user is, and send back a unique access token. (You'll also send back a refresh token that Google will use in the same way to get an updated access token.)
An auth token handler in your webhook. When API.AI calls your webhook, it will include the access token as one of the fields in the request. You can use this access token to get the Firebase ID for the user.
One thing to note for the auth code, the access token, and the refresh token is that you'll need to have some way to map from these codes/tokens to the Firebase ID. There are two good ways to do this:
The code/token can be a JSON Web Token (JWT). This takes the Firebase ID, and other information you wish to retain about the user, and puts it in a standard format. It then creates a cryptographic signature, to make sure it hasn't been tampered with, and encodes it in a standard format. When you need to determine the ID from the JWT, you can decode it, verify the signature is valid, and read the value.
Generate a random string and store this in your database against the Firebase ID. When you get the token, you can then look up in your database the ID that this string was assigned to.
There are many additional details about an OAuth implementation and about each of these steps. See https://developers.google.com/actions/identity/oauth2-code-flow for more details.

Is it possible to anonymously call API App and it automatically redirect the browser to AD Login page?

During the recent Microsoft Cloud roadshow in London, something that came out of one of the talks on App Service was using AAD B2C for authentication.
It is possible currently to add Azure AD as an authentication for an API App:
Calling this API app from a browser based web app with no authorization header results in a 302 redirect immediately followed by a 401 response.
It was mentioned at the cloud event that it would be possible to call an API app anonymously from a web app, and have the azure App service handle the redirection to the AAD login page, get the token on successful login and then pass the call on to the API app and return the data.
However, I am struggling to see how this can be achieved without any responsibility on the calling web app to handle the redirect. Normally you would handle a 401 response from an API by obtaining a bearer token via AAD on the client side and sending it through as the authorisation header with the api request.
I have been through numerous examples on the Azure site and others and all of them are handling the logon/obtaining the token in the client web app.
Is this even possible?
UPDATE I just realized (as pointed out by #Darrel-Miller that you don't really want to allow the user to put the credentials in.
The only thing that is still unclear to me, is where do you want to provide the credentials for AAD?, What is it exactly what you would like to accomplish.
Even more, why would you use AAD if there no user interaction at all.
If all that you want is a secure connection you can just use the standard application key for the web api without enabling AAD. And its as pretty straight forward to just add the MS_ApplicationKey to your header and you are good to go.
As you described in your comment you have a webclient that tries to do the requests and gets the 302, that is why my original answer wast that you would use ADAL. But now that I get deeper into what you want probably what you want to use is KurveJS :
https://github.com/MicrosoftDX/kurvejs
And it has the AAD app model v2 with Active Directoy B2C.
This makes it easy to add third party identity providers such as Facebook and signup/signin/profile edit experiences using AD B2C policies
You can read more about it here:
https://github.com/MicrosoftDX/kurvejs/blob/master/docs/B2C/intro.md
Do you mean this??
https://msdn.microsoft.com/en-us/magazine/dn463788.aspx
Just use ADAL nuget package to handle the call...
You can read this from the post:
As soon as the execution hits the call to AcquireToken, you’ll get the authentication dialog shown in Figure 8. ADAL takes care of contacting the right endpoint and rendering the authentication experience provided by the server in a pop-up dialog without requiring you to write any UI code.
I hope this works for you!

Self Hosted Web API Authentication

I have a self hosted Web API running, which using DotNetOpenAuth to issue authorization tokens. Basically, the project consists of 2 ApiController endpoints (Authorize and Token). I would like to force the client to have to log in to a form, prior to being able to call either endpoint. (Forms Authentication I guess). However, doesn't seem like it works for self hosted Web API projects, so, I am trying to implement something myself.
As of now, when the user calls the Authorize web get method, I render the login page and force them to login. However, I would like to have a mechanism in place so that once the user logs in, I can send a cookie response. I understand that if you write the cookie in the response, the browser will automatically send any relevant cookies upon subsequent requests.
However, my test client uses a HttpWebRequest to call my web api. Do I have to build the mechanism to save the response cookie to a file on the hard disk, and then, read it back, and associate with the HttpWebRequest on subsequent requests? Or , is there something built into the framework which I can leverage (just like how a browser would automatically take care of this for me).
I figured that once I could figure this part out, I could just extend the AuthorizationFilterAttribute, and use that to check the validity of the incoming cookie.
Thanks. Any help or suggestion is appreciated!

Resources