how to get client secret for a service account for google api - google-api-nodejs-client

This page:
https://console.cloud.google.com/iam-admin/serviceaccounts
if you go into an individual project that has a service account, and use the three dots on that row to execute the action "Get Key", it will generate a json that looks like:
{
"type": "service_account",
"project_id": "project name",
"private_key_id": "sdfljsdlfsdljkf",
"private_key": "-----BEGIN PRIVATE KEY-----\nsldjflsdjfkljsdf\n-----END PRIVATE KEY-----\n",
"client_email": "user#projectname.iam.gserviceaccount.com",
"client_id": "9797979797998",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/projectname.iam.gserviceaccount.com"
}
This doesn't match with what is needed for google.auth.OAuth2(client_id, client_secret, redirect_uris[])
What do I do to create a token to use with google spreadsheets api that uses this key information. It seems that the redirect_uris and the client secret are missing.
Update: the goal of this is to send google calendar events as other users under our domain.

I believe your goal and situation as follows.
You want to use Sheets API using the service account.
You want to achieve this using googleapis for Node.js.
You have already enabled Sheets API at API console.
In this case, google.auth.JWT is used instead of google.auth.OAuth2(). A simple sample script for this is as follows.
Sample script:
Before you use this script, please set the variable for google.auth.JWT(). In this case, as a samplet, client_email and private_key are set. And please set Spreadsheet ID. And, in this case, please share your sample Google Spreadsheet in your Google Drive with the email of the service account. By this, the service account can read the Spreadsheet.
const { google } = require("googleapis");
const spreadsheetId = "###"; // Please set Spreadsheet ID.
const auth = new google.auth.JWT(
"###", // Please set client_email here.
null,
"-----BEGIN PRIVATE KEY-----\n###\n-----END PRIVATE KEY-----\n", // Please set private_key here,
["https://www.googleapis.com/auth/spreadsheets.readonly"],
null
);
const sheets = google.sheets({ version: "v4", auth: auth });
sheets.spreadsheets
.get({ spreadsheetId: spreadsheetId })
.then(({ data }) => console.log(data))
.catch((err) => console.log(err));
Note:
When you run above script and an error like The caller does not have permission occurs, please confirm that whether the Spreadsheet of spreadsheetId is shared with the email of the service account again. If it is not, please share it with the email of the service account.
Please confirm whether the version of googleapis is the latest one.
References:
googleapis for Node.js
Method: spreadsheets.get

Related

Social Login using Google and Facebook in Flutter App

I am trying to implement my own server authentication (email, password) along with Facebook, and Google login. I would like to list what I have searched. Facebook login only returns an access token while Google login returns an access token and an id token.
I am planning to create my own JWT token in the backend, so which parameters (id token/access token) should be passed to my backend server to verify if the end user is logged in using Facebook or Google? I have some confusion about whether the access token is being used for authorization instead of authentication.
The token you get from google and facebook contain user data eg email, profile image etc you need to decode them.
Assuming email is unique in your db then you can query if exists and generate tokens on success.
example on how to decode google tokens in python
TLDR
from google.oauth2 import id_token
from google.auth.transport import requests
# (Receive token by HTTPS POST)
# ...
try:
# Specify the CLIENT_ID of the app that accesses the backend:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
# Or, if multiple clients access the backend server:
# idinfo = id_token.verify_oauth2_token(token, requests.Request())
# if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]:
# raise ValueError('Could not verify audience.')
# If auth request is from a G Suite domain:
# if idinfo['hd'] != GSUITE_DOMAIN_NAME:
# raise ValueError('Wrong hosted domain.')
# ID token is valid. Get the user's Google Account ID from the decoded token.
userid = idinfo['sub']
except ValueError:
# Invalid token
pass
Response
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}

get Id ( not clientId) from keycloak jwt token

JWT only gives the user information and clientId, how can I get ID of the client as shown in the image
I CAN GET CLIENT DETAILS PARTICULARLY ID FROM THIS URL
https://${SERVER_URL}/auth/admin/realms/master/clients?clientId=test
API RESPONSE
{
"id": "12af651d-f6fe-49ef-8e6f-b951a49ff7db", // want to add this id into JWT
"clientId": "test",
"rootUrl": "${authBaseUrl}", ......
}
but I want to save my api call for getting Id
How can I get client information "Id" within jwt?
Now this is showing on the extraction of jwt
{
exp: 1627981808,
iat: 1627974608,
sub: '923666de-0b37-42f0-b694-0491028d0b78', // user Id
typ: 'Bearer',
azp: 'test', // client id
acr: '1',
scope: 'openid email profile',
email_verified: false,
name: 'name123',
preferred_username: 'name123',
given_name: 'name123',
email: 'any_name#gmail.com'
}
Any help/information will be helpful for me.
You should create and deploy a SPI to your keycloak instance. That's a JAR that overrides standard behaviour. There are various SPIs both described in the documentation and as code in GitHub keycloak repo.
With that SPI you can add just about anything to your token. I would suggest not to change anything that exists in the default token as this might impact your OID compatibility.
See more details here and here.

using postman to access firebase REST API

I'm trying to use postman to do REST API calls to firebase. I've managed to read from firebase when my security rule is to permit all users including unauthorized ones.
but when I use this rule :
{"rules":{".read": "auth != null", ".write": "auth != null"}}
I get 'error' : 'permission denied' from postman.
I did the request token for google's web oauth2.0 client and got the authorization_code token back.
I tried to use token in the URL and in the header, tried it with GET & POST request and still get denied.
please help.
Thanks in advance
The answers above did not work for me.
What did work for me was going to
Project Settings (top left corner gear) -> Service Accounts (far right tab) -> Database Secrets (left menu) -> Scroll down, hover over the bulltets and click Show
Use this as the auth key, i.e. .../mycollection.json?auth=HERE
For me it worked like this:
https://your-database-url/users.json?auth=YOUR_AUTH_KEY
Where can you get this AUTH_KEY?
you get this key from your Project Settings -> Database -> Secret Key
Try something like this
https://your-database-url/users.json?auth=YOUR_AUTH_KEY
Respone is a JSON of your USERS node
I created a Postman pre-request script for helping create a Authentication: Bearer JWT. Should save a lot of copy pasting when testing APIs with Firebase Auth. https://gist.github.com/moneal/af2d988a770c3957df11e3360af62635
Copy of script at time of posting:
/**
* This script expects the global variables 'refresh_token' and 'firebase_api_key' to be set. 'firebase_api_key' can be found
* in the Firebase console under project settings then 'Web API Key'.
* 'refresh_token' as to be gathered from watching the network requests to https://securetoken.googleapis.com/v1/token from
* your Firebase app, look for the formdata values
*
* If all the data is found it makes a request to get a new token and sets a 'auth_jwt' environment variable and updates the
* global 'refresh_token'.
*
* Requests that need authentication should have a header with a key of 'Authentication' and value of '{{auth_jwt}}'
*
* Currently the nested assertions silently fail, I don't know why.
*/
pm.expect(pm.globals.has('refresh_token')).to.be.true;
pm.expect(pm.globals.has('firebase_api_key')).to.be.true;
var sdk = require('postman-collection'),
tokenRequest = new sdk.Request({
url: 'https://securetoken.googleapis.com/v1/token',
method: 'POST',
body: {
mode: 'urlencoded',
urlencoded: [{
type: 'text',
key: 'key',
value: pm.globals.get('firebase_api_key')
},
{
type: 'text',
key: 'grant_type',
value: 'refresh_token'
},
{
type: 'text',
key: 'refresh_token',
value: pm.globals.get('refresh_token')
},
]
}
});
pm.sendRequest(tokenRequest, function(err, response) {
pm.test('request for access token was ok', function() {
pm.expect(response).to.be.ok();
});
const json = response.json();
pm.expect(json).to.an('object');
pm.test('response json has needed properties', function() {
pm.expect(json).to.have.own.property('access_token');
pm.expect(json).to.have.own.property('token_type');
pm.expect(json).to.have.own.property('refresh_token');
const accessToken = json.access_token;
const tokenType = json.token_type;
const refreshToken = json.refresh_token;
pm.environment.set('auth_jwt', tokenType + ' ' + accessToken);
pm.globals.set('refresh_token', refreshToken);
});
});
Note: Adding this answer as all Options listed here is either deprecated or not working(mostly due to missing steps).
Best way to make it work with Postman is to use Google OAuth2 access tokens. The provided link described in full length but I have added quick steps.
Step 1: Download Service-Accounts.json
Step 2: Generate Access token in Java (provided link described support in other language for this)
make sure to include this dependency:
implementation 'com.google.api-client:google-api-client:1.25.0'
OR
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.25.0</version>
</dependency>
Run this code to generate token(Copied from google's javadocs)
// Load the service account key JSON file
FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");
GoogleCredential scoped = GoogleCredential
.fromStream(serviceAccount)
.createScoped(
Arrays.asList(
"https://www.googleapis.com/auth/firebase.database",
"https://www.googleapis.com/auth/userinfo.email"
)
);
// Use the Google credential to generate an access token
scoped.refreshToken();
String token = scoped.getAccessToken();
System.out.println(token);
Step 3: Use the token in Postman
It is very simple to fetch data via Postman:
Here is how I did it
1 Your DB URL
https://YOUR_PROJECT_URL.firebaseio.com/YOUR_STRUCTURE/CLASS.json
2 Add API key in header as auth
auth = Value of your API_KEY
example:
We can use Firebase with postman for rest APIs
How we use Firebase in postman?
Copy your Firebase database URL
Paste it into your postman URL
Add .json at the last like shown in the image
Then play with your firebase database and make REST API

DocuSign: setting user permissions using REST APIs

For creating a group, a user and assigning the user to that group, I referred this link Add permission profile through API.
Using REST APIs I am able to do that but permission for user is not getting set.
When I check in DocuSign, group is having correct permission set but same is not set for a user. Please let me know if I am missing anything.
Additional Information: This is the request I am sending
{
"newUsers":[{
"email":"'.$email.'",
"userName":"'.$userName.'",
"password":"'.$password.'",
"groupList": [{
"groupId": "'.$groupId.'",
"groupName": "'.$groupName.'",
"permissionProfileId": "'.$permissionId.'"
}]
}]
}
Also, when a user is added to a group, permissions set at group level will be applied to the users. Is there something missing?
When you create a permission profile you use this endpoint:
POST {vx}/accounts/{accountid}/permission_profiles
the response body for that endpoint should contain this info ( I omitted some details from the response)
{
"permissionProfileId": "sample string 1",
"permissionProfileName": "sample string 2",
...
}
Once you have the permissionProfileId and permissionProfileName you should be able to assign that permission profile to a user using this endpoint:
PUT {vx}/accounts/{accountid}/users/{userid}
and using the permissionProfileId and permissionProfileName in your request (I used dummy values here):
{
"permissionProfileId": "12345",
"permissionProfileName": "SomeName"
}
I hope that helps!
-Yadriel

google cloud storage public url, to use in img src

first, i have read, searched google and everywhere. but i cant find the solution to my problem. I can upload images to my google cloud storage bucket. then, i want to get the public URL, so i can save it to my mongodb, and access it later on for my site.
I have a code here, written in GO.
// profile func, that receive filename, and file
name, self_link, err := google_storage.Upload(handler.Filename, file)
// then after acquiring the self_link, i update the user
db.UpdateUser(session_id.(string), db.UserUpdate{"ProfileImage": self_link})
the problem is, i can't access the file from my link to my pages when passing it to the html..
i guess, my links aren't public?
here is my oauth config
config := &oauth.Config{
ClientId: clientId,
ClientSecret: clientSecret,
Scope: storage.DevstorageFull_controlScope,
AuthURL: "https://accounts.google.com/o/oauth2/auth",
TokenURL: "https://accounts.google.com/o/oauth2/token",
TokenCache: oauth.CacheFile(cacheFile),
RedirectURL: "https://www.example.com/oauth2callback",
AccessType: "offline",
}
from there after authorizing my web server, i can just
// my object setup
object_to_store_data := &storage.Object{Name: fileName}
result, err := service.Objects.Insert(bucketName, storage_data).Media(file).Do()
any help is appreciated, im new to google cloud storage, and go.
thank you in advance