Google App Engine service-to-service authentication (non-programmatic) - google-app-engine

I have a scenario where I have an on-premise GUI application which has a "Web Service Invoke" component which I use to call a GAE API.
In the GUI application, it is possible to:
store credentials
create a chain of web services/http(s) calls that can integrate an output of preceding https(s) call as a query parameter or header value into the next http(s) call
retrieve a value from JSON response of the http(s) call
But it is not possible to programmatically do anything. The Web Service widget has fields for passing API URL, query parameters and headers only.
I'm looking to do a service-to-service authentication for the API call and the API should be protected using IAP as well.
I'm aware of the recommended approach is to create a service account and provide the service account JSON key file to the client and the client signs a JWT token and pass it as a bearer token. But as I only have widgets, no programming possible, therefore signing JWT token is not an option.
I was looking at Google OAuth or IAM APIs which can support "client_credentials" grant type wherein I can get an access token using just clientId and clientSecret - something possible in Apigee. But it seems this grant type is not supported by Google OAuth APIs.
I also looked at Cloud Endpoints using API KEY - so the current thought is to the client passes API KEY in header/parameter for authentication to Cloud Endpoints, then Cloud Endpoints uses its service account to get access through IAP, and finally, I'm thinking that the client can also send in "Basic Auth" credentials through Authorization header which the GAE API backend service validates. The additional "Basic Auth" is because Google recommends using another auth method in addition to API KEY.
I would like a simpler solution if possible using GAE and IAP only. Any other suggestions, especially using time-limited tokens, that can work over only http(s) calls (non-programmatic or client library), is much appreciated.
Any alternatives or things to try is also appreciated.

Look into this server-to-server authentication using JWT Google API Authentication

Related

Microsoft Graph - OAuth2.0 flow for React client and spring-boot backend

I am building a React-based SPA that communicates with a spring-boot backend via a REST API. I need the user to be able to log into their Microsoft account on the browser client (the SPA) and I need the backend service (spring-boot app) to be able to query Microsoft's Graph API on behalf of that user.
After reading up on the Oauth2 flows, the authorization code flow (not the PKCE flow, just the regular authorization code flow) seems the most appropriate. The browser client could let the user log into their Microsoft account, retrieve an authorization code, and send the authorization code to our backend service via HTTP request. The backend service (which is trusted and can safely store a client secret) can then request an access token, make requests to the Graph API directly (meaning that the SPA would never need to make any requests to the Graph API), and silently refresh the token as needed.
However, I cannot see any examples of anyone using this flow to access Microsoft's Graph API.
Looking at Microsoft's documentation, it seems like they recommend using the on-behalf-of flow. But this flow requires the browser client to request an access token and then use that to communicate with the backend service (which in turn can communicate with the Graph API). It doesn't make sense to me why the access token cannot be requested on the backend using a client secret. Wouldn't this be a more secure and preferred method than having the client retrieve the access token, as is done in the on-behalf-of flow?
The Oauth2.0 site, recommends that SPAs should either use the authorization code with PKE or the implicit flow, but I do not see an option to use the standard authentication code flow for SPAs. Should I take this as an indication that SPAs should not be using the standard authorization code flow as I described earlier?
Despite not finding a clear-cut example of the standard authorization code flow in Microsoft's documentation for a react frontend + java backend, I tried to go about doing this myself. However, using the #microsoft/mgt-react and #microsoft/mgt-element libraries to do this are not straight forward. For example, the #microsoft/mgt-element notion of a Provider supports a call to retrieve an access token, but doesn't clearly expose the authorization code. If I wanted to do the authorization code flow described earlier, it seems like I would need to use raw HTTP requests, which I know is not a recommended way of accomplishing this.
Summarizing my questions:
What OAuth2.0 flow should I be using: 1) authorization code (access token is retrieved by backend service using client secret), 2)
authorization code with PKE (access token is retrieved by client), or
3) on-behalf-of flow (access token is retrieved by client, seems to be an extension of PKE flow)?
If using the on-behalf-of flow, does the SPA just include the access token in the header (marked as 'bearer') and the backend service just
includes that same header to query the Graph API, or does the backend
service need to request another token before querying the Graph API?
Agree with #ch4mp to call graph api directly in SPA if it's allowed. If not, then I recommend you using on-behalf-flow or client credential flow based on your requirement.
Let's come back to your requirement -- call ms graph api in a springboot api project. First, let's see one of the graph api getting user api. You can see permission types here: Delegated which means call graph api on behalf of the user, Application which means calling api on behalf of the application(your spingboot api project) itself. If you want to call api behalf of the user, then you have to use on-behalf-of flow. This is because the api project which will be considered as a daemon application, so the project itself doesn't have a UI page to let users enter username/password to sign in and get authenticated.
You can certainly use ROPC flow which have to pass the username/password to api but I really think it unsafe, so I don't recommend.
If it's not necessary for you to call graph api on behalf of user, you can certainly take client credential flow into consideration. But pls note here, application type api permission is a "large" api permission which always have name like User.ReadWrite.All, Mail.ReadWrite.All and it always means the application can not only query user information but also be able to modify user information.
If you want to use on-behalf-flow, then you may review this answer and it explained the whole progress...
I would use authorization-code flow (with PKCE) to get an access-token and then refresh-token flow to "maintain" this token, both from client.
Authorizing the request to your resource-server with this token only makes sense if Microsoft authorization-server is your main authorization-server. Otherwise (user also logged in with an authorization-server of your own or not using OAuth2 betwean React and backend), you can still send Microsoft access-token in request body.
In any case, when issuing requests in the name of the user from the backend, do as you suggest: just set the access-token sent by the client as Bearer Authorization header (token is retrieved either from Spring security context or request body). Backend fetches a new access-token (using client-credentials flow) when issuing requests in its own name (without the context of a user).
Side note: have you considered calling Microsoft API directly from React client? If you don't have to store the result of that call on your resource-server (i.e. call graph API to display data and store only what user selected from that data), that would save quite some latency on the client and costs (network and CPU) on the backend.

Right way to use federated login (Google, FB etc) between a client & server

I have seen this solved in popular platforms like Android & iOS using client SDKs. My question is
I have a RESTful server
I have a mobile client
How to
Create a signup which uses a federated OAuth (Google, FB, Microsoft etc) and use that to further authenticate the subsequent API calls.
This is what I am thinking
Client application calls the OAuth dialog of the login provider, and receives (after user consent), access token and user ID.
This is stored on the client and also passed to the server.
Server can validate (retreive) user info using the accessToken.
Sever can return IDtoken/Refreshtokens which client can use in subsequent API calls.
My question here is
Is this the right approach.
Can clients store the accesstoken (best practice?)
Can client pass the accessToken to backend (best practice?)
Is there an example, how this can be implemented for Google Auth (for a client and Webserver) without using SDKs.
The standard option is to implement the AppAuth pattern in your mobile app, meaning it signs in and uses tokens from your Authorization Server (AS). The mobile app then sends access tokens to your APIs.
Once this is done, signing in via Google, Facebook etc requires only config changes in the AS. Adding a new login / identity provider requires no code changes in either your UIs or APIs.
Here are Android and iOS samples of mine that use this approach and which you can run and maybe borrow some ideas from.
They use AWS Cognito as the AS - and I could configure Cognito to use Google or Facebook logins if I wanted to. Also I am in full control of scopes and claims added to access tokens - which my APIs can use to authorize requests.
ANSWERS
Almost right - your client app redirects to the AS and not Google / Facebook directly
Yes - mobile clients can store a refresh token in OS secure storage private to the app so that users do not need to login on every app restart. My samples do that.
Yes - mobile clients use access tokens as API message credentials
LIBRARIES
I agree with you here - avoid Google / Facebook libraries in your app. However it is recommended to use the respected AppAuth libraries - once integrated your app is compliant with any AS and will support all of its authentication flows.
Out of interest the AppAuth pattern even potentially enables future advanced scenarios such as App2App, since the AS can federate to an AS from another company (though I doubt that is relevant to you right now).
LEARNING CURVE
Finally it's worth mentioning that it is tricky to implement AppAuth - there are annoyances - but once done the architecture is in a good place.
Firstly, Any application that calls Google APIs needs to enable those APIs in the API Console.
Now, Any application that uses OAuth 2.0 to access Google APIs must have authorization credentials that identify the application to Google's OAuth 2.0 server.
For the credentials go to the Credentials Page and then fill the form according to your Application.
Note: Google recommends that you design your app's auth endpoints so that your application does not expose authorization codes to other resources on the page.
After getting your credentials, download the client_secret.json file from the API Console and securely store the file in a location that only your application can access.
For HTTP/REST, there is no need to install any libraries to call oAuth 2.0
Google's OAuth 2.0 endpoint is at https://accounts.google.com/o/oauth2/v2/auth. This endpoint is accessible only over HTTPS. Plain HTTP connections are refused.
As a client, the only thing you need to do for Basic authentication is to include an Authorization header in an HTTP request, composed of the username and password, separated by a colon and then Base64 encoded. E.g., in Ruby (1.9) using RestClient:
require 'restclient'
require 'base64'
auth = "Basic " + Base64::strict_encode64("#{username}:#{password}")
response = RestClient.get("https://myhost/resource",:authorization=>auth)
The token value is opaque to a client, but can be decoded by a Resource Server so it can check that the Client and User have permission to access the requested resource.
Authorization: Bearer <TOKEN_VALUE>
Send user to Google's OAuth 2.0 server. Example URL:
https://accounts.google.com/o/oauth2/v2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly&
access_type=offline&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http%3A%2F%2Foauth2.example.com%2Fcallback&
response_type=code&
client_id=client_id
Request access token. Example:
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code
Use API. Example:
GET /drive/v2/files HTTP/1.1
Authorization: Bearer <access_token>
Host: www.googleapis.com/
Is this the right approach.
Yes, pretty much. You're describing standard bearer token authorization. Access & ID tokens expire after a short time frame, and you have to use a long-lived refresh token to get new ones. The access token allows you to gain access, the refresh token is only useful for bootstrapping tokens.
Can clients store the accesstoken (best practice?)
Yes. You must store an OAuth refresh token. You may store the ID and access tokens (as opposed to keeping them in memory.)
On the web, you should not use Local Storage. Instead, use an httpOnly cookie.
On mobile, use platform features like Android's AccountManager or iOS' Keychain Services.
Can client pass the accessToken to backend (best practice?)
Yes, that's its purpose.
Is there an example, how this can be implemented for Google Auth (for a client and Webserver) without using SDKs.
I do not recommend this for several reasons. Firstly, your implementation will be less secure than Google's, who has a team devoted to ensuring their SDK is the most secure it can be. Secondly, you're not ready to try this implementation, yet. Start with the SDK, get it working, and then come back to this.
Using a solution like Auth0 will be the easiest way to start.

React SSO using SAML without web server

I have a web app developed using Create-react-app
I host it on IIS, the IIS only response to load the app, there is no server side logic on it (no Express or any other web server)
The app is using a RESTful API on the same IIS, it is out of my control (I cannot make change).
Now one of my client request to add SAML SSO to our app.
I would like to know:
in normal situation, which one is the Service Provider? My IIS Web server? or the API service?
For my case, I cannot implement SAML to API service, my web service only used to load my app without server side logic, how can I implement SAML?
Could any one give me some React implement SAML SSO tutorial or article for reference?
Thanks for any help, any information or suggestion are welcome!
in normal situation, which one is the Service Provider? My IIS Web server? or the API service?
I assume the client wants to authenticate the users using their internal IdP. So your application is the SP. But you will have to define different token service (details below).
With SPA (a single-page-applications) I see the problem, in SAML the user is redirected or posted away from the SAML request and SAML response.
I have a login page to enter id/pw, post them to API server Login endpoint to authenticate and get back a JWT token. After that we use that token in API calls for authentication
The API services are using a JWT token issued based on the provided username/password. I'd recommend to extend the token service (or use a different service) to issue a JWT token based on the provided SAML response - a token swap service. In many OAuth implementations it's called SAML grant type.
I cannot implement SAML to API service, my web service only used to load my app without server side logic, how can I implement SAML?
Usually after the authentication the user is redirected or posted to the SAML ACS endpoint URL, where the server can create sort of session (cookie, parameters, token, ..) and the user is redirected to a URL returned the web page with the session information.
If you are using an SPA, you could use a popup window or SAML with redirect (not with post), where the page could read the SAML response parameters (assertion, signature, ..) and use them in the token swap service mentioned above.
When processing the SAML response, try to use some mature, known, out-of-box libraries, it's a security service and not doing it properly may cause security weaknesses. But you need to do that on the server side, as at the end you need the JWT token consumed by the APIs.

Access Token for both Microsoft Graph and Custom API

I have a ReactJs frontend making requests to an API. Both hosted in Azure with app registrations in AAD as well.
I used to be able to use v1.0 auth endpoint, and create a valid token for the API:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=<AAD_WEB_APP_ID>&resource=<AAD_API_ID>&response_type=token ...
If I understand the documentation correctly, this type of auth flow isn't allowed/possible in v2.0:
However, that Web API can receive tokens only from an application that has the same Application ID. You cannot access a Web API from a client that has a different Application ID. The client won't be able to request or obtain permissions to your Web API.
The reason for changing from v1.0 to v2.0 is that I need access to Microsoft Graph (Groups in particular).
My question is: How can I create an access_token that works for Microsoft Graph and my API? If that isn't possible, what would the correct auth flow be?
You don't need to switch to the v2 Endpoint for this, Microsoft Graph supports both v1 and v2 tokens (actually, every API I can think of that supports v2 also supports v1 but there might be an exception I'm forgetting).
The steps are pretty straightforward:
Update your AAD registration in the Azure Portal and add the Permissions for Microsoft Graph you're going to be using.
Instead of passing resource=<AAD_API_ID> in your URI, use resource=graph.microsoft.com. This will return a token that can be used with Microsoft Graph.
Important: You must request the Offline Access scope (offline_access) for this to work.
Where this gets confusing is that technically you cannot use the same Access Token to access both your API and Microsoft Graph. What is supported is switching the Resource when refreshing your token. So while, yes, you are using two different tokens, you're reusing the same credentials/authorization code.
Here is an example flow:
A user authenticates using your API as the Resource (resource=<AAD_API_ID>). This returns an Authorization Code back to your application.
The application posts the Authorization Code to the /token endpoint (also using your API as the Resource). This will return both an access_token and a refresh_token to the application.
Use this access_token to make calls into your API.
The application posts the refresh_token to the /token endpoint using graph.microsoft.com as the Resource. This will return a new access_token and refresh_token keyed to Microsoft Graph.
Use this new access_token to make calls into Microsoft Graph.
The application again posts the refresh_token to the /token endpoint but this time using your API as the Resource again. This will return a new access_token and refresh_token keyed to your API.
Call your API
You can repeat this cycle as needed. Depending on how often you need to switch, you can also keep access tokens for both your API and Graph in memory and reuse them until they expire. Just be sure and always store the last Refresh Token you received so you can fetch a refreshed token for either resource as needed.

Securing RESTful API in Google App Engine

I'm trying to figure out how to implement the following authentication flow:
The user accesses a web application (most likely to be written using Ruby on Rails) and authenticates (e.g., username/password).
The client consumes data via AJAX provided by a RESTful API built on Google App Engine (Python, webapp2).
Requirements:
Only users authenticated in the web application (Rails) should be able to access the API hosted on App Engine.
Users can have different roles in the web application (Rails), and the API (App Engine) needs to know what roles are associated to the given user to restrict access to certain data.
The client should be able to call the API (App Engine) directly via AJAX, without routing all requests through the web application (Rails).
I'm looking for suggestions on how to implement such workflow. Should I use OAuth (or OAuth2) for accessing the API? Should the OAuth provider live on App Engine and the web application (Rails) ask the API for a token on behalf of the user? If so, what is the best way to allow only the web application (Rails) to request OAuth tokens? Or should I consider a completely different strategy?
Any suggestions are greatly appreciated. I'm also looking for suggestions of libraries to implement OAuth in the context above.
I suggest you use caution if you are considering implementing an API built on the Google App Engine using OAuth for your security layer. I am currently involved in a project that is struggling to solve exactly this problem. The OAuth layer over the GAE is still new and considered by Google to be "experimental". Google's documentation is minimal at this point. What there is begins here. I wish you the best if you try to proceed, and I will do my best to offer help if you do.
My solution to this same problem was to write my own three-way authentication (like OAuth):
After the user is authenticated on the RoR server, it responds with a temporary token. This token is stored on the RoR server, is good for 60 seconds, and contains the user's roles.
The browser sends this token (using AJAX) to the webapp2 server. It's like logging in on that server using just the token.
The webapp2 server forwards the token on to the RoR server to make sure it is valid.
The RoR server makes sure the token hasn't expired and immediately deletes the token to prevent duplicate requests. If the token is valid, the RoR server responds with the user's roles.
If the response from the RoR server is good, the webapp2 server responds to the browser's AJAX call (in step 2) with a cookie indicating that this user is now logged in. The session should contain the user's roles.
Subsequent requests to the webapp2 server will include the cookie so that server can respond according to the user's roles.

Resources