What do I need to add to my web request for GCP Cloud Function Security? - security

My HTTP Cloud Function is working fine, but it is public. After testing it out I used the GCP console to restrict it to a particular user (ie my own Google account) and, as I expected, I get 403 when I send requests to it. This is good. But I don't know what I need to add to my request for it to get past Google's security. I assume it wants to check a header for a token and verify it against the IAM, but I haven't found any examples yet.
There's a lot of information about using Cloudflare for this, and also someone has done some clever work building an OAuth check inside their cloud function. But clearly Google is already doing a security check for me (this may be new functionality) and I would rather use that than build my own. To be specific then, I went into the permissions section of my Cloud Function and added a member to the 'Cloud Functions Invoker' role. I can add AllUsers as a member and the CF becomes public, take it out and I'm back to 403 responses. So the security is definitely working. I just need a way to identify the caller.
Does anyone know how to add the right keys or whatever to the request?

Some more reading and I found the answer here
The answer is that CFs are, indeed, doing OAuth so my request needs to look something like this:
curl https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME \
-H "Authorization: bearer $(gcloud auth print-identity-token)"
That's using the gcloud command to pull the JWT down and put it in the header. To actually make it work I needed to create a service account and download its key (to the file referred to below). I then added that to the CF (in permissions) and then used
gcloud auth activate-service-account --key-file=sa-cf.json
to make that my currently active account so that the token printed was for that account. Beware when doing this because the tokens quickly expire so if you're pasting them into Postman (as I was) it won't work if you leave it any time before sending the request.
Hope this helps someone else.

Related

SubscriptionKeyInvalid in Azure API Management for an endpoint in a product that does not require subscription?

I have a very strange issue with Azure API Management, that I don't seem to figure out...
We have an API operation that is part of an APIM API that is linked with a Product that does not require a subscription. The intention is that this API endpoint is publicly available for consumers, without requiring any subscription keys, headers, etc...
When I call this endpoint from Postman, it works.
When I just do a GET to the endpoint in a private browser session (so nothing added in headers, etc), it works.
When I execute the API operation from the Azure APIM portal, without selecting a product, it works.
But, when I call the endpoint from a deployed web app in Azure App Service, I get a 401 back?!
So, the obvious thing is that something is misconfigured, but I cannot get my head around it...
When looking in Application Insights, linked to the APIM instance, this is the trace, I see:
But in the following screenshot, I get a hint of the mismatch, though I don't understand how this happens... If I copy the full url to a browser private session, I get back a 200 with successful data.
But the root cause of the 401 is probably in the yellow box, where there is an API product dev-product-admin, which indeed requires a subscription (and has JWT token policies configured). So, what I need to find out now, is how I can make sure that APIM is linking my incoming request to the right product, which doesn't require a subscription. Any hints?
And two minutes after writing down the question, you get your own insight...
I checked the code and I was adding a SubscriptionKey header to that specific call (because of a configuration issue). And that subscription key was obviously making the link to the specific Product (which indeed requires more authorization)

Authenticating with Azure EasyTables - Azure ActiveDirectory

I've been attempting to authenticate requests to an Azure App Service for some time now and I'm completely stumped, I just can't seem to get the Microsoft.Azure.Mobile.Client to accept and successfully authenticate against a known "good" token.
Overall, all I want is to be able to successfully pull up a web browser in Xamarin Forms, authenticate the user either with Azure, Google or other social authentication, and then use a token to authenticate against an Azure App Service (EasyTables), which I already have running but without authentication enabled. For some reason none of the resources I've found have provided an clear way of doing this, and I'd be grateful for any help.
Here's the main config of what I have so far:
I've got an app successfully reading and saving data tables to an Azure-hosting EasyTables implementation. Tables are read (and written) using the standard form:
var locations = (await App.MobileService.GetTable<Location>().ToListAsync());
The MobileServiceClient is instantiated in the App.xaml.cs file as follows:
public static MobileServiceClient MobileService = new MobileServiceClient("https://mywebapp.azurewebsites.net");
As I say above, this works fine when access to and saving from online services.
Going to the Azure Portal, I've activated "App Service Authentication" under Settings --> Authentication / Authorization, and I've also set up an Azure Active Directory Authentication Provider. Under this provider I've set up the Client ID of an Azure Active Directory instance (under Manage --> App Registrations).
Going back to Xamarin, I have successfully managed to authenticate against this using the approach by Steven Thewissen here. In particular, I've created an "MSAuthService" helper, which successfully pulls up a web browser, allows you to log in with Microsoft credentials, following which it's able to retrieve your account name and verious other things from Microsoft Graph - including the Access Token.
I'm now trying to use this access token to log into the MobileService I'm using to access EasyTables, using the following:
JObject auth_token_jobject = new JObject();
auth_token_jobject["authenticationToken"] = token;
var output = await App.MobileService.LoginAsync(
MobileServiceAuthenticationProvider.MicrosoftAccount,
auth_token_jobject);
However, whenever I do this, I still get an "Unauthorized" error, produced by the last line above.
I understand that others (e.g. here seemed also to have the same problem, but no resolution on that post.
Other things that I've tried, but haven't managed to get working completely. As above, the closest I've got, by successfully authenticating albeit through Microsoft Graph rather than with my web service specifically, is the process above:
Overview of Authorization with EasyTables etc here - although this doesn't seem to provide any clear code for Xamarin to authenticate against.
Latest Xamarin blog and explanatory materials (here and here, but although the process using await WebAuthenticator.AuthenticateAsync method appears to be a lot simpler than the example I was using above, there doesn't seem to be any detail provided about how you generate the URI required to call the authentication page, nor a step by step guide of how to implement it. Either way, I haven't managed to get it working...
If anyone has an easy way of getting hold of a valid token and then providing it to the MobileService client, I'd be most grateful. I suspect it's as simple of getting the token called back, for example from a Xamarin Essentials WebAuthenticator above, and then passing it with var output = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount,auth_token_jobject) but I just can't seem to get it working so far.
Thanks a lot!
Oliver.
There are a couple of issues here (on re-reading it a few times)
You are using MobileServiceAuthenticationProvider.MicrosoftAccount - you should be using "aad" instead.
AAD needs an access token - see https://learn.microsoft.com/en-us/azure/app-service/app-service-authentication-how-to#validate-tokens-from-providers for the details on what needs to be provided.
If the token you get back is really an MSA token, then you still need to provide an access_token field (and not an authenticationToken field)
If you don't need anything special, you should be able to just use .login() like this:
await App.MobileService.LoginAsync("aad", "your-method");
For more details on this, see one of the authentica

How to allow a public app to connect to the GitHub API v4 without an access token?

I have decided to try to manage releases of one of my apps on GitHub as with GitHub Actions, I can build on Mac, Linux and Windows and automatically push the artifacts to the GitHub Releases page, where anyone can go and download the app from.
However, I want my app to self-update, so the app itself also needs to be able to query what's the latest version in the repo releases, and then download the relevant asset for the user's OS... which I thought would be a non-issue... however, there's no way to access the GitHub API v4 without either an OAuth app or a personal access token.
I don't want an OAuth app because the users of my app are absolutely not expected to be GitHub customers. So I tried to use a personal access token whose only scope was access to public release assets (which, again, is a public resource anyone can go and manually download).
As this token can't do anything you or anyone else can't do manually, even without a GitHub account, I thought it would be fine to put the token in the source code of my application, but GitHub revokes the token when it detects it on a commit.
Is there a good way to work around this? Should I put the token in a GitHub secret and then try to replace a placeholder with it during compilation?? I wanted to avoid that as that makes it hard for me to test the app locally, and also, it doesn't solve anything as anyone can easily decompile the app and find the token there (supposing GitHub would not detect the secret is present in the "processed" sources during compilation).
Any suggestions would be appreciated.
however, there's no way to access the GitHub API v4 without either an OAuth app or a personal access token.
The GitHub API v3 does support unauthenticated calls, but it's limited to 60 requests/hr per IP address: https://developer.github.com/v3/#rate-limiting
For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Unauthenticated requests are associated with the originating IP address, and not the user making requests.
The Latest Release API docs will show you what information is returned, but I suspect you'll need to make a secondary call to List Assets for a release to know the files the client needs to download.
If that's not satisfactory (e.g. you know you'll have many clients try to update using the same IP address), and you'd like to ensure they aren't being rate-limited, read on for a different approach.
Is there a good way to work around this?
How I would tackle this is by deploying a small web service (e.g. Heroku dyno) that your app can will call without needing authentication, which then performs the actual lookup for the latest version (using a PAT that gets embedded as an environment variable) and returns a simple JSON response that the client will understand.
Benefits:
no token embedded in client
development mode can even call same service
add logic to service that the client would perform to simplify your app
e.g. call /latest/beta or /latest/stable to indicate it's looking for a specific channel
perform both API calls and return the assets that the client needs
can update token in service whenever necessary (e.g. to refresh token) without changing client
can cache response to reduce risk of being rate-limited
Downsides:
more moving parts to manage in your overall architecture
need to worry about uptime of the service if there are lots of clients connecting
this can be offset by making the client resilient to failure cases

When registering an app on Azure Active Direct, what "redirect URI" or "Sign-on URL" should I use?

Might seem a silly question, but Microsoft's documentation isn't very beginner friendly, I think. It uses as examples "http://localhost:31544" for the sign-on url and "http://MyFirstAADApp" for the redirect URI, but although I understand what a local host is I can't figure out what exactly the numbers on it are and how I define them for my application, and absolutely zero clue of what the redirect URI is supposed to do for a native application and how should I define a URI for my own.
To be more clear on what kind of app I'm trying to add, I merely want to acess the Office 365 management API tools and get some data from it, so I imagine a native app would fulfill my needs for now. Registering the app on Azure AD is required to do so according to Microsoft's documentation.
So expanding on the title, how to define an URI for my native app is what I would mainly like to know. Some further clarification on what exactly is the purpose of this URI as well as to how to use and/or define a localhost URL for an Web app would also be much appreciated.
I know this is ancient, but I don't see a satisfying answer here, and maybe someone will come across this and find it useful. To answer the question asked, unless you're going to work outside of the default MSAL handling of the server responses, and I don't expect you would from your description, I'd just go ahead and use the default:
https://login.microsoftonline.com/common/oauth2/nativeclient
When you go into the Azure AD portal, go to your application and, from the Overview, select the "Set RedirectURL" option, you'll add a platform and select the "Mobile and Desktop Applications" and you'll be provided with the choice of 3 URLs to choose from. My understanding is this is just there for custom handling of authorization tokens and is telling MS where to send those tokens. The MSAL library functions seem to use this link as well, so they're probably handling this in the backend.
I agree with the OP though, the MS docs are severely lacking for newcomers and I wasn't able to find an end-to-end description of what needs to happen to get, in my case, a desktop application to send email through Office365 using 2FA. I would forge ahead as best I could until I hit the next error, then explore that, sort it, then slam into the next one. Rinse and repeat. This was made extra tedious as I had to go through a 3rd party IT group to get the 2FA access codes every time I wanted to test.
Best of luck, hope this helps someone!
how to define an URI for my native app is what I would mainly like to
know.
You should provide a Redirect URI that is unique to your application as it will return to this URI when authentication is complete.
In your application, you will need to add a class level variables that are required for the authentication flow, include ClientId and Redirect URI.
Here is the diagram:
Native application makes a request to the authorization endpoint in Azure AD, this request includes the Application IP ,Redirect URI and application ID URI for the web api.
After user signed in, Azure AD issues an authorization code response back to the client application's redirect URI. After that, the client application stops browser interaction and extracts the authorization code from the response.
Then the client app use this code to sends a request to Azure AD's token endpoint. upon successful validation, Azure AD returns two tokens.
Over HTTPS, the client app uses the returned JWT access token to add the JWT string with a “Bearer” designation in the Authorization header of the request to the web API. The web API then validates the JWT token, and if validation is successful, returns the desired resource.
More information about it, please refer to this article.
For native you can set redirect to be equal to the Application ID URI, which now defaults to look like //app:{ApplicationId}
Redirect uri be starts with SSL URL, so select your project, enable SSL URL and use this auto generated SSL URL (for example : https://localhost:port#) as redirect uri , same to be updated in the azure app registration as additional redirect URIs

Create a token for Resource Management Node Azure SDK

I've been using the Node Azure SDK over the last few days, everything is going well except for the fact that I cannot find any documentation on how to create an access token for the ResourceManagement API. It seems this doesn't use the PEM + SubId like the other API's in the SDK.
I did find the MSDN docs but they are .Net specific and assume the token is generated via a .dll file. Does anyone have any experience with generating this token via Node?
EDIT:
For reference I have asked on the repo first but have yet to get a response (holiday season)
I think you have to use Active Directory http://blogs.msdn.com/b/tomholl/archive/2014/11/25/unattended-authentication-to-azure-management-apis-with-azure-active-directory.aspx
For anyone else looking to do this:
You need to do a service to service type OAuth call. This is slightly different to authenticating the user as most documents show.
The link below pretty much walks you through it. I've tested in postman (chrome) and have successfully got a token back.
http://msdn.microsoft.com/en-us/library/azure/dn645543.aspx

Resources