Authorizing REST API calls to GCP - google-cloud-platform

I am totally new to GCP products. I am trying to create and manage the resources i.e. Virtual Machines using the REST API's provided in the documentation. One of the endpoints which I am trying is
GET https://compute.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instances?key={API_KEY}
Though to make authorized calls to the platform I need to configure the OAuth 2.0 authentication for which I created the relevant service account. I am not sure how to further use it to authorize the requests. Any leads on this would be greatly helpful. Thanks!
Edit:
I intend to call the REST APIs from Python. Not sure if that's the right way.

I was finally able to authorize the API calls to GCP by creating JWT, serializing it to UTF-8 representation (UTF-8 is important), signing it using the google client library google.auth and finally making a request to https://oauth2.googleapis.com/token having passed POST parameters grant_type = urn:ietf:params:oauth:grant-type:jwt-bearer and assertion whose value is the signed jwt for the token using the signed JWT token.
Reference: https://developers.google.com/identity/protocols/oauth2

Related

AWS Cognito Hosted UI -- How to use the returned JWT token?

I am using Amazon Cognito and its hosted UI to help create a web application. I am able to use to log in using the hosted UI and the redirect link successfully points me to where I want it to go. I also recieve a correctly formatted JWT token on redirect.
I've also successfully parsed that JWT token into a JS object and am able to verify its validity. With the correct username, expiration time, issue time, etc., etc.
The problem I'm having now is that I simply don't know where to go from here. Is the fact that I have that JWT enough to continue on and assume that the user is valid? If I want to be able to persist the user across different webpages on the site, is it safe to store the JWT -- or, at least, parts of it -- in session storage and act as if that is valid user?
If not, then what am I supposed to do next with the JWT? I have looked through many of the various articles on using the JWT with Cognito and they all seem to be about decoding the JWT, but not about what I'm supposed to do with the JWT once I have it decoded.
For context, all I am really trying to get from the JWT is the correct user name, I am planning on storing a lot of other important user details elsewhere.
I'm sorry if there is something very obvious I'm missing about where to go next, but I'm very new to all this AWS stuff and a lot the of documentation is confusing, and not beginner friendly. Thank you for your time, any help at all is greatly appreciated.
EDIT: I wanted to include that I am writing the log in / verification / redirect code on vanilla, client-side javascript. I am using the standard aws SDK, the aws-cognito SDK, and the amazon-cognito-identity SDK. My imports look like this:
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.686.0.min.js"</script>
<script src="../../aws-cognito/dist/amazon-cognito-auth.min.js" type="text/javascript"></script>
<script src="../../amazon-cognito-identity-js/dist/amazon-cognito-identity.min.js"></script>
my advise for you would be to look into the AWS Client Side SDK which handle the storing, refreshing and other nice functionality for you.
https://docs.amplify.aws/start/q/integration/js - Main Client side SDK.
https://github.com/amazon-archives/amazon-cognito-auth-js - older SDK used for Cognito Oauth endpoints/ Hosted UI.
Both SDK's will store the result from your HostedUI authentication is local storage in the browser. There you can check if the tokens are valid and even access them if you require to send them to an authorized resource server.
This of course can all be implemented without the use of those SDK's but they help and can give you poinnters. Additionally, the AWS SDK and Cognito identity SDK do not have any functionality that will help you integrate with the HostedUI and Oauth endpoints. That can be done using the SDK's provided above.

How to use JWT with Ballerina

I read about JWT and i think i understand how it works, but when things come to ballerina examples i don't understand anything:
How do i set the algorithm which i want to use along with JWT and the expiration time?
How do i use a custom private key?
How can i get the token from this example for instance "https://ballerina.io/learn/by-example/secured-service-with-jwt-auth"?
May be how can i get the token using CURL (for testing purposes)?
Also i'm wondering how to use the JWT without the need of having a database with users and passwords..
I'm absolutely new to security and ballerina also. Can anybody help please?
Ballerina JWT module [1] provides following functionalities.
Issue a JWT
You can issue/generate a JWT by providing jwt:JwtIssuerConfig. You can configure username, issuer, audience, expiration time, signing algorithm, custom claims and configuration for signature (key-store config). Please refer to API docs of jwt:JwtIssuerConfig [2]. Example code can be found at [3].
Validate a JWT
You can validate a JWT by providing jwt:JwtValidatorConfig. You can configure expected issuer, expected audience, clock skew, cache configuratons and configurations for validating signature (trust-store config). Please refer to API docs of jwt: JwtValidatorConfig [4]. Example code can be found at [3].
Secure a service with JWT
You can use JWT to secure and HTTP service. The Authorization header of the inbound HTTP request will get validated and authenticated according to the provided configurations. Please refer to API docs of jwt:InboundJwtAuthProvider [5]. Example code can be found at [6].
Calling to a service with JWT
You can use JWT to call to an external server which is authenticated with JWT. The outbound HTTP request is prepared with the Authorization header according the provided configurations. Please refer to API docs of jwt:OutboundJwtAuthProvider [7]. Example code can be found at [8].
Answers for the questions:
How do i set the algorithm which i want to use along with JWT and the expiration time?
You can configure jwt:JwtIssuerConfig [2] as described above.
How do i use a custom private key?
You can configure the jwt:JwtKeyStoreConfig field of jwt:JwtIssuerConfig [2], with your custom private key.
How can i get the token from this example for instance "https://ballerina.io/learn/by-example/secured-service-with-jwt-auth"?
May be how can i get the token using CURL (for testing purposes)?
This is a sample service which is secured with JWT. The token used to invoke this service is provided at the bottom of the sample. How to invoke this service with CURL is also provided.
Also i'm wondering how to use the JWT without the need of having a database with users and passwords..
All of the above samples, does not need any database or file store. All the configurations are provided in the code itself. If there is any requirement to retrieve data from database, that is also possible.
References:
1 https://ballerina.io/learn/api-docs/ballerina/jwt/index.html
2 https://ballerina.io/learn/api-docs/ballerina/jwt/records/JwtIssuerConfig.html
3 https://ballerina.io/learn/by-example/jwt-issue-validate.html
4 https://ballerina.io/learn/api-docs/ballerina/jwt/records/JwtValidatorConfig.html
5 https://ballerina.io/learn/api-docs/ballerina/jwt/objects/InboundJwtAuthProvider.html
6 https://ballerina.io/learn/by-example/secured-service-with-jwt-auth.html
7 https://ballerina.io/learn/api-docs/ballerina/jwt/objects/OutboundJwtAuthProvider.html
8 https://ballerina.io/learn/by-example/secured-client-with-jwt-auth.html

How to get an oauth2 authentication token from google cloud (in codename one) and then use it to make a request to the cloud natural language API

I am trying to build an app in codename one with the cloud natural language api but I am struggling to figure out how to first get authentication from oauth2 and then make a request to the api.
I have read the quickstart for the cloud natural language api and followed all of the steps. I can make requests to the api from the gcloud command line but I want to be able to make requests from codename one. I want to use oauth2 to get authentication and have an oauth2 client ID but I do not know how to get the authentication token. I have read about it here https://www.codenameone.com/google-login.html but I do not know what to put HERE on line 5 of the following code. Once I have the oauth2 authentication token, I do not know how I will make a request to the api from codename one. I have read about requests to the natural language api here https://cloud.google.com/natural-language/docs/reference/libraries but it did not say how to make a request from codename one.
Login gc = GoogleConnect.getInstance();
gc.setClientId(clientId);
gc.setRedirectURI(redirectURI);
gc.setClientSecret(clientSecret);
gc.setCallback(**HERE**);
if(!gc.isUserLoggedIn()){
gc.doLogin();
}else{
//get the token and now you can query the gplus API
String token = gc.getAccessToken().getToken();
}
In summary, I do not know how to get an oauth2 token from codename one and then make a request to the cloud natural language api with that token.
You should use a slightly newer version of this article here under the "Google Sign-In" section. The token is returned in this line of code String token = gc.getAccessToken().getToken(); but it will only work within the callback code when login was successful.
You will need to use the REST API to make the requests to the server as covered here: https://cloud.google.com/natural-language/docs/reference/rest/
That way it will work for all supported platforms.

Django API fronted by Azure API gateway

I have a Django application that currently stores user credentials and performs authorization and authentication. I am in the process of breaking off the front-end into an Angular SPA and converting the backend to a REST API. My Django API will live as an Azure API app protected by Azure API Gateway. I would like to remove the authentication piece from Django and allow users to sign in using OpenID Connect through either Google or Microsoft Account. What I would like to happen is this:
When a user visits the site, assuming they have never registered with my app, they will have the option to sign in with their Google account or Microsoft Account. If the user decides to sign in using their Google or Microsoft account, (this is where I'm confused and why i'm posting here ... ) I think what happens is the API Gateway performs the authentication, generates a JSON Web Token (JWT), and sends that token back to the Django API. Django receives the JWT, decrypts it, and checks to see if there is a user account matching the email address in the JWT. If there is not a user account, Django will add a user to the user accounts table (not storing a password). If there is a user matching that email address, then Django allows the user in.
All that said, I guess my question(s) are:
Should I do the authentication at the API Management Gateway or should I do it at the Azure Web API?
Can I use Django's built-in authentication system to do what I want or is that not needed?
Am I over-complicating all of this? Is there an easier way to do this? All this seems like a lot of work.
Is OpenID Connect what I should be using (instead of Oauth2)? I have no experience with either.
Azure API Management does not actually provide any kind of JWT issuing mechanism, so you'll have to implement that yourself. The end points for doing that may or may not be exposed via API management.
What possibly gets you confused is the fact that the APIm Portal supports various indentity providers, like Twitter or Google, to sign up for the API. But these are not your application users, these are for the API Portal Users.
What you can do with the APIm Gateway is to validate subsequent calls to your backend API that the supplied JWT token is valid (using the <validate-jwt> policy).

Generate an OAuth2 token in a view

Let's say I have an AngularJS application that consumes the REST API of a Django application.
The Django application has got a built-in OAuth2 provider that can be called to retrieve an access token and use the protected endpoints of the API. This provider is using django-oauth-toolkit.
Let's assume there is a registered client with "password" grant type, so that the end users only need to provide their credentials in the front-end in order to get an access token from the back-end.
At some point we want to add some support for social networks login and we decide to use python-social-auth (PSA) to that end. Here is the workflow I want to achieve:
The user logs in on Facebook from the front-end (via the Facebook SDK) and we get an access token back from the OAuth2 provider of Facebook.
We send the Facebook token to an endpoint of our REST API. This endpoint uses the Facebook token and django-social-auth to authenticate the user in our Django application (basically matching a Facebook account to a standard account within the app).
If the authentication succeeds, the API endpoint requests an access token from the OAuth2 provider for this newly authenticated user.
The Django access token is sent back to the front-end and can be used to access the REST API in exactly the same way that a regular user (i.e. logged in with his credentials) would do.
Now my problem is: how do I achieve step 3? I first thought I would register a separate OAuth2 client with Client Credentials Grant but then the generated token is not user-specific so it does not make sense. Another option is to use the TokenAuthentication from DRF but that would add too much complexity to my project. I already have an OAuth server and I don't want to set up a second token provider to circumvent my problem, unless this is the only solution.
I think my understanding of PSA and django-oauth-toolkit is not deep enough to find the best way of reaching my goal, but there must be a way. Help!
I managed to get something working using urllib2. I can't speak towards whether or not this is good practice, but I can successfully generate an OAuth2 token within a view.
Normally when I'd generate an access token with cURL, it'd look like this:
curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/
So we're tasked with making urllib2 accomplish this. After playing around for some bit, it is fairly straightforward.
import urllib, urlib2, base64, json
# Housekeeping
token_url = 'http://localhost:8000/auth/token/'
data = urllib.urlencode({'grant_type':'password', 'username':<username>, 'password':<password>})
authentication = base64.b64encode('%s:%s' % (<client_id>, <client_secret>))
# Down to Business
request = urllib2.Request(token_url, data)
request.add_header("Authorization", "Basic %s" % authentication)
access_credentials = urllib2.urlopen(request)
json_credentials = json.load(access_credentials)
I reiterate, I do not know if this is in bad practice and I have not looked into whether or not this causes any issues with Django. AFAIK this will do this trick (as it did for me).