decoding Firebase idToken on Google App Engine - google-app-engine

My firebase users are sending requests to my API server. I am verifying them using security rules in Google Cloud Endpoints. I extract their userID without using admin SDK on Google App Engine.
Normally, Google suggests verifying incoming id Tokens for a HTTPS request via this code in their example Firebase Cloud Functions code:
admin.auth().verifyIdToken(idToken).then((decodedIdToken) => {
console.log('ID Token correctly decoded', decodedIdToken);
req.user = decodedIdToken;
return next();
}).catch((error) => {
console.error('Error while verifying Firebase ID token:', error);
res.status(403).send('Unauthorized');
});
However, in the example Google App Engine code, Google decodes the token without the admin SDK:
let authUser = { id: 'anonymous' };
const encodedInfo = req.get('X-Endpoint-API-UserInfo');
if (encodedInfo) {
authUser = JSON.parse(Buffer.from(encodedInfo, 'base64'));
}
I am using Google Cloud Endpoints to secure my API hosted on Google App Engine. I have set security on cloud endpoints to allow only firebase users to access the routes, however, I only want users to access their own data so I need to decode their id token to retrieve their userID. I was wondering if Cloud Endpoints handles the authentication here. Do I need to have admin SDK verify the token? or the simple decoding in Google's example is secure enough because cloud endpoints already takes care of verifying the idToken?

The Admin SDK is doing what the Endpoints proxy is doing in verifying the token. The proxy is just passing along the verified token. As long as the Endpoints proxy remains in front of your app, you can just decode the X-Endpoint-API-UserInfo token.

Related

Oauth for authorization JWT for authentication for an app using DRF and cloud functions

I'm building a web app with Wagtail as back-end, running on app engine, cloud functions doing micro-services and triggered via http.
I want to let my users register and authorize using social apps and classic login-password and get a JWT token from Wagtail App. Then, the token will be used to authenticate users both on cloud functions and Wagtail back-end.
How do I provide the user with JWT tokens if he/she authorizes with OAuth?
Is my approach correct? Any suggestions on how this should be done in the proper way?
The best solution I found so far is to use firebase auth. In python I verify token like that:
from firebase_admin import auth
decoded_token = auth.verify_id_token(id_token)
uid = decoded_token['uid']

Access Google IAP protected API from Angular

My application has 2 modules
Spring boot back-end API
Angular front-end (SPA application)
Both were deployed in Google app engine (GAE).
I used Google IAP for authentication. After enabling the IAP is there any way to generate the IAP JWT token for the different users within the organization to authenticate the APIs from the web client.
I tried token generating mechanism using the Service account. But for my scenario, I just want to authenticate and authorize users not service account. I found this reference to enable the web resource access for users, but it is using cookie based authorization. And it is not the recommended way for the application such as angular.
If you're using IAP to protect your backend api, it means your users have a Google Account or an account managed in Cloud Identity.
In your Angular front-end app, you can retrieve JWT token of your user, with Google Sign-In for Websites.
To easily integrate Google Sign-in with Angular, I recommend you to use ng-gapi from Ruben.
Main lines of the workflow :
Angular uses ng-gapi with Google Sign-in behind the scene
Users are authenticated with their Google Account
You're able to retrieve GoogleUser idToken which is a JWT token.
Each HttpRequest could be executed with Authorization: Bearer JWT
IAP will accept request.
To better understand how to use ng-gapi, check this stackblitz Demo made by creator of lib.
I also suggest you theses resources :
My answer on Stackoverflow about Angular stateless authentication workflow. Just skip the Spring Boot JWT part if you're using IAP.
Google Sign-In for Websites official docs.
Note that you need to use the OAuth 2.0 Client ID configured by Identity-Aware Proxy for your app, and add the correct Authorized JavaScript origins.
Yes, You can generate a JWT token using angular-oauth2-oidc.
Get the default IAP Web App client ID and client secret. Use AuthConfig and redirect to your link after credentials are entered; you can capture the token after they are redirected.
This link has all the details:
https://medium.com/#ishmeetsingh/google-auth-integration-with-angular-5-and-angular-oauth2-oidc-ed01b997e1df
You have told that you tried authenticating from service account. Were you able to generate JWT for service account? I am able to capture the JWT token for individual accounts and use it.
Please give more information on how you authenticated from service account.
Thanks,
Bharath

Retrieve Access Token within a AAD secured Azure Web App

I have an Angular4 Application hosted in an Azure Web App and a .NET core Web API hosted in an Azure API App.
The API is secured with Azure Active Directory. Currently I use ng2-adal to aquire an access token which I inject to the headers to perform my API calls.
Now I try to remove the ng2-adal module and secure my Web App with the Authentication / Authorization feature using the same ClientId (like the API). When I browse to my website I get redirected to the AAD login and after I successfully login, I get redirected to my site. Now I wan't to call the API (that is secured with the same ClientId) within my Web App but can't find a way to retrieve the token.
Is there a way to retrieve the access token within my Angular App in this scenario?
It looks like the token is stored encrypted within the AppServiceAuthSession Cookie:
The AppServiceAuthSession is cookie which is different than a token. In this scenario, you need to modify the config of Azure app to make it acquire the access_token for the web API.
We can use the Resource Explore to modify the settings like below:
1 . locate the angular web app
2 . locate the config->authsettings(resource is the clientId of Azure app which used to protect your apps)
"additionalLoginParams": [
"response_type=code id_token",
"resource=3fa9607b-63cc-4050-82b7-91e44ff1df38"
],
3. config the redirect_uri for Azure app like below:
https://appfei.azurewebsites.net/.auth/login/aad/callback
Then after you login in the angular app, you can get the access_token via the endpoint:
https://appfei.azurewebsites.net/.auth/me
Then we need to protect the web API using the Advanced Azure Active Settings like figure below to enable the access_token could call the web API:
I've been working on this for a week.
So, I'd like to share how I got it.
I was able to have authentication for my app using AAD.
I have AppServiceAuthSession in my cookies storage.
Then on my application, I called the auth/me API.
https://yourwebsite.azurewebsites.net/.auth/me
So, it's like:
this.$http
.get('https://yourwebsite.azurewebsites.net/.auth/me').then(response => {
console.log(".auth/me", response)
}, err => {
console.log("Error: ", err)
})
I'm actually using Vue. calling your HTTP might be different.
And that's it.
I basically called the auth/me API to retrieve the information I needed.
P.S. You need to be authenticated of course.
found this solution:
just need to add your app url on
Authentication / Authorization-> ALLOWED EXTERNAL REDIRECT URLS
so the webapi will automatically accept those cookies.
ps: make sure your ajax request is passing those cookies on it.

How to call REST API in google app engine

I have 2 GAE. GAE1 has REST API (Tastypie without implementation of oauth authentication). GAE2 calls the REST API of GAE1.
If calling the API:
data = urllib2.urlopen("http://___GAE1____.com/api_ws/api/v1/test/?format=json").read()
the returned result is sign-on page, not JSON result from GAE1.
How to perform authentication hosted by GAE? OAuth2 or API key?
I read https://developers.google.com/api-client-library/python/guide/aaa_oauth
But could not figure out what is client secret, scope (my REST API or some google cloud API?)

OAuth issues with Google App Engine And Google Apps Script integration

I am trying to use Google Apps Script in Google Spreadsheet and have an OAuth issues.
The Spreadsheet and Google App application are both protected by Oauth provided by Google as I am using Google Apps for Business.
Below is the script I am using. It gives me the oauth dance but fails to invoke the URL and retruns with a 302 response.
Not sure what to do next. have tried setting auth callback hadler and everything but did not get far. I also have ScriptProperties being set for key and secret (not seen below). Also the scope is not set as App Engine indicates that OAuth is for the entire app.
I get a 302 response at the end of this, after Google App Engine telling me that an app is requesting access. It also indicates that appspot.com is an external provider
var oAuthConfig = UrlFetchApp.addOAuthService("google");
oAuthConfig.setAccessTokenUrl("https://<blah>.appspot.com/_ah/OAuthGetAccessToken");
oAuthConfig.setRequestTokenUrl("https://<blah>.appspot.com/_ah/OAuthGetRequestToken");
oAuthConfig.setAuthorizationUrl("https://<blah>.appspot.com/_ah/OAuthAuthorizeToken?hd=<blah.com>");
oAuthConfig.setConsumerKey(consumer_key);
oAuthConfig.setConsumerSecret(consumer_secret);
var requestData = {
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always"
};
var response = UrlFetchApp.fetch(url, requestData);
You can't use the consumerKey and consumerSecret on AppEngine api's. AppEngine is not part of the authorization/configuration used for Google Apps for Business. Try without them and revoke the permissions granted already or change the name (from "google") to something else.

Resources