GCP GCS Oauth grant type - authentication

I have a tool where I need to setup a flow that upload a file to GCS (granting rights to a service account).
Problem of the tool is that it's an UI and only support a "Oauth 2.0 Grants type Flow".
It asks for:
Authorization Server URL
clientId
client Secret
It doesn't seems possible to have an authentication by a service account with only these 3 parameters: Authorization Server URL, clientId and a client Secret
Problem of this application is that it can't use code. Otherwise I would have used Python and do it easily.
From what I understand of Oauth2 in GCP for a service account:
https://developers.google.com/identity/protocols/oauth2/service-account
https://cloud.google.com/bigquery/docs/authorization
We need to generate a JWT token by doing some signing with base64 and sha256. This is not a possible solution because the app can't use code or such algorithms.
I have the same problem with interoperability system and HMAC keys: https://cloud.google.com/storage/docs/aws-simple-migration
which requires a signature: https://cloud.google.com/storage/docs/authentication/signatures
It seems that the task is impossible unless I missed something.
Thanks for any help !

Since your software has a UI and it's asking for url/cliendID/secret there is a good chance that it will perform the token generation for you using the oauth2 protocol.
Try with the following:
Url -> https://accounts.google.com/o/oauth2/auth
ClientID -> your service account email
Secret -> your service account key secret (you have to generate a key in JSON format from the GCP Console UI by selecting the service account)

Related

difficulties making Cloud Run service the target of an Apps Script project--audience and scopes

I am unable to create an OpenID Connect identity token to send as bearer token for a cloud run request. From the apps script I cannot make a token using (ScriptApp.getIdentityToken()) which has an audience the Google front end will allow through. When I arrange for the script to send a token instead that I've made with gcloud print-identity-token--identical except for the audience--that invocation succeeds.
Note I believe this may the same issue as seen here: Securely calling a Google Cloud Function via a Google Apps Script.
Also google cloud authentication with bearer token via nodejs.
One workaround suggests restructuring the GCP/Apps Script projects. Others mostly use service accounts, and use service account keys. I believe it's possible using IAM and use of google auth for one to produce a usable SA identity token (short term service account credentials) but I can't demonstrate it.
I am working around this currently, but I'd like to understand the essential problem. I think it has something to do with the cloud run service's hosting project's Oauth consent screen, and the inability to add the associated web application client-id as a scope.
In the Cloud Run docs, there is a section about performing authenticated calls to Cloud Run from other services outside GCP. The process would be the following:
Self-sign a service account JWT with the target_audience claim set to the URL of the receiving service.
Exchange the self-signed JWT for a Google-signed ID token, which should have the aud claim set to the above URL.
Include the ID token in an Authorization: Bearer ID_TOKEN header in the request to the service.
Step 1 could be performed as described here while setting the aud claim to the URL of the receiving service. I believe ScriptApp.getIdentityToken() does not set the proper audience to the JWT
For step 2, I believe you should perform a POST request to https://oauth2.googleapis.com/token with the appropriate parameters grant_type and assertion. This is explained in the "Making the access token request" section here
The resulting token should be used in step 3
I just wrote an article on that topic and I provide an easy way based on the service account credential API. Let's have a look on it and we can discuss further if required.

Securing an existing API with our own solution

I have to design a mobile application that interacts with a provided API to exchange data and info, and I've read about API security, Oauth 2, tokens, .... etc, but something still not clear to me, the following are the important points:
API provided by a 3rd party as a black box, no security implemented,
so you can query for data belongs to any user.
a user should use our application, sign in with a user/password and get access to his data only. (must be very
secure, because we should pay a lot if security was broken)
the solution needs to be implemented and self-hosted, not from a third party or cloud provider.
example of an API call:
....base url...../{subscriber-ID}/offers
the above call get the suitable offers for a subscriber whose ID is {subscriber-ID}, so obviously, without security, I can query offers for any subscriber, but my goal is to link between user/password and querying only data related to the desired user.
I read a lot, but I'm confused since I'm new to API security.
so where should I start? how can I benefit from Oauth 2 in my case? just need a roadmap, not how to implement.
oAuth2 using spring security is a solution for this requirement.
There are 4 grant types in oAuth2 which is meant for different scenarios.
client credential : the consumer (app) make calls to back-end using the bearer token created using apikey(or clientId) and secret only. Mostly used for anonymous calls where generic information is retrieved.
Resource owner password credential (ROPC) : the consumer (app) make calls using the bearer token created using apikey, secret, username and password. Mostly used when you(your authorization server) already know the users(user database is handled in your own system).
Authorization code : the consumer (app) make calls using the bearer token created using an authorization code. The authorization code is provided by a 3rd party (which actually has/manages the logged in user data) and the created authorization code linked to the logged in user. Google and Facebook log in for various sites is a typical example. Facebook/Google gives an authorization code for those websites and they exchange that code for a token.
Implicit grant : Mix of password credential and authorization code. Instead of authorization code, you get a bearer token from the 3rd party authorization server.
I have been searching a lot for a simple sample code for an authorization server, but never found one. So, I tried to create it myself which you can find here : https://github.com/abbinv/oauth2Server. Only ROPC and Client Credential is implemented.
It is not a 'beautiful' code. But i think you will get the basics.

Can I use OneLogin API to generate SAML assertions in a standalone app?

I want to use OneLogin to write a command-line program that takes a username/password and generates a SAML assertion that can be used to authenticate to other sites.
The problem is that calling the "Generate SAML Assertion" API itself requires an access token generated from API credentials. So to distribute my app to users would require me to bake in API credentials to make that call. That would be fine, but the only authorization profile that allows callers to POST to the SAML resource is "Manage All", which is way more permission than is safe to give.
Has anyone done something like this?
OneLogin people, can you add an API credential type for calling only the SAML Assertion APIs? Or you could just make the API open. (Note that AWS's "AssumeRoleWithSAML" API doesn't require user credentials -- the whole point of the API is that you have credentials you want to convert to another credential type.)
Do you give a developer a personal application to generate the SAML token or do you build a web service that returns a SAML token?
The former is bad (since the app has the key) the latter is infinitely more secure.
When we do lower the required rights to get a SAML assertion with a key (ID & secret) you should still look into building this as a web service. One your command line tool should call to get the SAML assertion.
Because contrary to popular opinion - Cloud-based means better security.
We will be publishing an update shortly to lower the type of token to "Read/Write Users," since you are simply exchanging the user's credentials for the SAML assertion. Will that suffice?
Note: I initially mistakenly wrote "Read" instead of "Read/Write"
There is now an Authentication Only API scope, which can be baked into your application.
The endpoints available in this scope include:
Verify Factor (SAML Assertion)
Generate SAML Assertion
Verify Factor (Login)
Create Session Login Token
Log User Out
Writing a web app to get the SAML assertation would be the best solution and let the CLI interact with it. Especially if you consider the "Log User Out", which can log out any given user as long as you can guess the ID (easy).
If you trust your employees you could embed an Authentication Only scoped client ID/secret in your CLI. This is exactly what we will do at the first step with our OneLogin AWS-STS CLI tool. Of course we could have a rogue employee abusing this, but it's an edge case and really easy to revoke the client ID/secret and rollout a new version with a new client ID/secret.

How to use oauth with 1st party client-side js app?

The model for our product is like this:
Api backend (headless)
I already have oauth set up and ready to use with a resource owner credentials grant. Anyone who wants to use our api can do so using either an API key or their username/password. Of course they also need their client ID and secret.
SPA frontend that accesses the Api
I have built an SPA that will uses the api to provide a portal GUI for our clients. Given that this client-side app is owned and administrated by us (so it's a trusted app) how can I safely authenticate users using only username/password with oauth?
Originally it was using a JWT auth system that only required username/pass but now that we've implemented oauth I'd like to consolidate. It's unreasonable to make every user need to also have their client id and secret on hand to login, but I want users to have full access to the api from the GUI.
I've looking at using CSRF tokens but how would that work with my app when nothing is generated server-side?
I'm not sure how to proceed.
EDIT: very similar to the problem here.
I have decided to use the solution described here.
And here is a snippet of my implementation
The TL;DR version is
Create a proxy between the app and the api
Store the client ID and secret in the proxy
App logs in using password grant type -- proxy intercepts login request and inserts client id and secret
On login response proxy returns access token as an encrypted cookie
Client stores cookie and sends with api requests (to proxy)
Proxy decrypts cookie and inserts access token into Authorization header before forwarding to api endpoint
For me this has several advantages over implementing something custom on the api itself:
No need for custom grant on oauth server
ID/secret is hidden from app securely and can still use password grant
oauth server can identify client (no need for separate client ids for each user)
You should not use the resource owner credential grant from a JavaScript application. The fact that you own and administer the application does not make it a trusted application.
A trusted client is an application that can keep a secret. SPAs or any JavaScript app cannot keep a secret.
You should use the implicit grant for non-trusted clients.

How to start with OAuth Client Credentials to protect WebApi using OWIN Oauth?

I am a newbie to OAuth 2.0.
I have fairly read the OAuth 2.0 doc and I saw there are four types of methods for obtaining Authorization.
Types of obtaining authorization:
1.Implicit Grant
2.Resource Owner Password Credentials Grant
3.Client Credentials Grant
4.Authorization Code Grant
In my case, I have Client application, Resource owner, Resource server and Authorization server.
Resource server is a website where Resource owner registers with his/her credentials.
Client application is a third party website who registers into resource server and gets the Client application credentials for accessing it in future.
Authorization server checks the client credentials from client app and grants access token to the client app.
Let us consider, resource server as "www.serversite.com", authorization server as "www.authserver.com" and client application as "www.clientapp.com".
Flow:
Step 1: Also make an assumption that www.serversite.com as a payment gateway site and the client has to integrate "www.serversite.com" into "www.clientapp.com" for creating, executing and refunding payments.
Step 2: So the client "www.clientapp.com" creates an app in server "www.serversite.com" and gets API credentials.
Step 3: Using these API credentials, the client "www.clientapp.com" makes an access token request to the auth server "www.authserver.com".
Step 4: If the API credentials from client app are valid then the auth server grants an access token.
step 5: With this access token, client app request the resource server for further operations like creating payments as well as executing payments.
My questions:
I am using ASP.NET Web API for authorization server and using OWIN.OAuth for generating access token, refresh token, authorization and all the stuffs needed to authorize the client app.
But, in this link (OWIN OAuth 2.0 Authorization Server), I found that, the web api authorize the client app using "Resource Owner Password Credentials Grant" and the sample provided for implementing Owin.OAuth in web api is great, but I have lot of confusions roaming in my mind.
Which way of obtaining authorization is suitable for my process?
(Client Credentials flow or Resource Owner Password Credentials flow)
How to implement Client Credentials Grant type using ASP.NET Web
API(OWIN OAuth)?
Also provide some samples or links that may be helpful for me?
Thanks in advance.
Theres an example of how to get started on the asp.net website, specifically here:
http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
I quote:
private Task GrantClientCredentails(OAuthGrantClientCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(
context.ClientId, OAuthDefaults.AuthenticationType),
context.Scope.Select(x => new Claim("urn:oauth:scope", x))
);
context.Validated(identity);
return Task.FromResult(0);
}
Obviously you will need to go ahead and verify the actual client id / secret exist perhaps in a local database sometwhere before you go ahead and set the context to validated.
In terms of deciding which flow to use, you need to ask yourself, if the application is requesting access to your APIs on behalf of an actual user, then you need to use Resource Owner, however if the application itself needs access then Client Credentials is the way to go.
Generally speaking though, most implementations use Authorisation Code Flow, so if you can form a security stand point, get the users redirected to a page you host to take their credentials, opposed to sending them over the wire via Resource Owner Flow.