I have a SPA that's supposed to interact with IoT Core and Cloud Pub/Sub through gapi.
First I used only IoT Core. I added the necessary scope both to the app configuration under APIs & Services / Credentials and my gapi client initialization call documented here.
It worked fine, the OAuth consent screen showed the new scope, IoT Core API calls were working.
Now I want to add Cloud Pub/Sub. Again added the scope to both the app configuration and the gapi initialization call. Here's the argument to gapi.client.init:
{
apiKey: config.firebase.apiKey,
clientId: config.clientId,
discoveryDocs: [
'https://cloudiot.googleapis.com/$discovery/rest?version=v1',
'https://pubsub.googleapis.com/$discovery/rest?version=v1',
],
scope:
'https://www.googleapis.com/auth/pubsub https://www.googleapis.com/auth/cloudiot',
}
Yet, when I make a call to the Pub/Sub API, I get this response:
{
"error": {
"code": 403,
"message": "Request had insufficient authentication scopes.",
"status": "PERMISSION_DENIED"
}
}
Here's what I tried:
log out and then back in
wipe browser cache and cookies
revoke all permissions from the app in Google Accounts
Still no luck. The interesting thing is that although now both scopes are added to the app on the cloud side, after revoking app permissions and logging back in, the consent screen requests permission only for the IoT Core scope. The Pub/Sub scope doesn't show up there.
Any ideas what I'm missing?
Found the problem. The login was initiated by another part of the code that didn't have the Pub/Sub scope added.
Related
I've written a simple Calendar API call using the official NodeJS client: https://github.com/googleapis/google-api-nodejs-client#service-account-credentials
It works fine on my local machine, using a Service Account set up with Domain-Wide Delegation to create the event and invite a list of attendees on my behalf.
I set the credentials location using GOOGLE_APPLICATION_CREDENTIALS env var on my local machine, but do not set this on the Google Cloud Run service because it's supposedly automatic since I've associated the Service Account. This assumption seems true because I can call GoogleAuth functions and get back the expected service account name.
However, once I try to run it in Cloud Run, it throws the error:
Error: Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.
At first I thought this was an issue with default credentials somehow loading the wrong service account.
I added logging directly before the event is called to see what account it is using:
const auth = new googleClient.auth.GoogleAuth({
clientOptions: {
subject: eventOwner
},
scopes: calendarScopes,
})
const serviceAcctName = (await auth.getCredentials())?.client_email
googleClient.options({
auth: auth
})
logger.info(`${serviceAcctName} acting as ${eventOwner}, using calendar ${calendarId}`)
const calendar = googleClient.calendar('v3')
const response = await calendar.events.insert(event)
The log output is exactly as expected, with the correct service account acting as the correct user on the correct calendar id.
I've double-checked that the account has domain-wide delegation of authority and the proper scopes, and it works fine on my local machine, so the only thing I can think of is something about the library's feature of grabbing default credentials in a Google environment is overwriting my googleClient.options() call. But I'm still confused because GoogleAuth functions still give the expected service account info when it grabs the 'default'.
I've implemented Google Calendar API. It works well. When I allow calendar integration in my app it asks for permissions to access calendars and everything works perfectly.
However, after a week or so the permissions just disappear.
api.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES,
}).then((data) => {
resolve();
I can see in the network tab that the request is passing correct scopes.
But the response from Google misses the calendar scopes.
Scope sent:
scope: openid profile email https://www.googleapis.com/auth/calendar
Scope recieved:
scope: "email profile openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
The only way how to make it work again is to remove permissions to my app in the google account and start the whole process again.
It drives me crazy. I triple checked everything. Any ideas are hugely appreciated.
Some more info if it helps:
It's happening in my localhost. It's all allowed in Google API.
I use Google Firebase for auth process in my app.
I have Register 2 application in Azour Ad ad following:
SPA React Application.
Web API application
I expose the web API custom scope as following:
And in the SPA application I add the permission as below:
After that in the React application I configure MSAL Login and it works fine but I face the following issue when I try to get the access token and specify the scope for the Web API scope I created before as code below:
function getAccessToken(){
console.log("get access token");
console.log("account user name " + accounts[0].username);
if (account) {
instance.acquireTokenSilent({
scopes: ['soe.all'],
account: account
}).then((response) => {
if (response) {
console.log(response.accessToken);
accessToken = response.accessToken;
}
});
}
}
I already Grant admin consent and the login is working fine but when I try to get the token it fails,
I need the access token to start calling the Web API which will be a Spring Boot Rest API.
I think you need to fully qualify the scope name so it is in the form <application-id-uri>/<scope-name>, so for you it would be https://<tenant-name>.onmicrosoft.com/soeapi/soe.all.
I have an old-school angularJs app that has two pages. On both of the pages I include the auth0 lock script.
<script src="https://cdn.auth0.com/js/lock/11.9.0/lock.min.js"></script>
Of those two pages, one has the following js that specifies an auth0 lock to allow users to login:
new Auth0LockPasswordless(configuration.id,configuration.domain,
{
allowedConnections: ['email'],
passwordlessMethod: "link",
auth: {
redirectUrl: configuration.redirectUrl,
responseType: 'token id_token',
params: {
scope: 'openid profile email offline_access'
}
}
}).show();
and the other page is responsible for the call-back after they've clicked the link in their email.
var lock = new Auth0LockPasswordless(configuration.id, configuration.domain);
lock.on('authorization_error',
function(authResult) {
console.log("DEBUG::AUTHRESULT::", authResult);
});
lock.on('authenticated',
function(authResult) {
console.log("DEBUG::AUTHRESULT::", authResult);
});
Now I've set offline_access in the scope of the request, and on my local environment been prompted for additional permissions when authenticating (so it's making it through). However when I check the log from the lock.on('authenticated', function(authResult).. refreshToken is always null.
There's some conflicting documentation around the web, with both suggestions that lock will and wont return a refresh token. Is anyone able to confirm if this code should result in a valid refreshToken?
As #user44 said above in the comments, you shouldn't use a refresh token in a SPA (Single Page Application), as it's not a secure client and way to store it securely. Instead, use the silent authentication approach to request new access tokens.
https://auth0.com/docs/api-auth/tutorials/silent-authentication
Depending on which SDK you're using, either auth0-spa-js or auth0.js:
https://auth0.github.io/auth0-spa-js/classes/auth0client.html#gettokensilently
https://auth0.com/docs/libraries/auth0js/v9#polling-with-checksession-
(Disclaimer: I work at Auth0 as Sr. Solutions Engineer)
Update (07. May 2020):
It should be noted that Auth0 recently introduced Refresh Token Rotation https://auth0.com/docs/tokens/concepts/refresh-token-rotation, which is also supported by the Auth0 SPA SDK
I use GSuite and I'm coding a very simple web app to use Google Auth API, and I get an exception "idpiframe_initialization_failed".
Now I have the exact HTML as shown in the google Sample:
https://developers.google.com/api-client-library/javascript/samples/samples
1) I've created a project on the Google Developer Console
2) I setup the OAUTH authorization screen
3) I've created the client ID, creating restrictions and redirection URL
4) I've also created the API KEY
5) Finally I've enabled the People API, because discovery services was failing when setting the discoveryDocs parameter
With all of these steps, When I call the gapi.client.init, it raises an exception ONLY in chrome, I cannot understand why.
The code for initializing the API is:
gapi.client.init({
apiKey: 'MY_API_KEY',
discoveryDocs: ["https://people.googleapis.com/$discovery/rest?version=v1"],
clientId: 'MY_CLIENT_ID.apps.googleusercontent.com',
scope: 'profile'
}).then(function (response) {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
},function(reason){
console.log('onerror');
console.log(reason);
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
The code is running the error block, and the message is:
details: "Failed to read the 'localStorage' property from 'Window': Access is denied for this document."
error:"idpiframe_initialization_failed"
Any ideas why I'm coming into this error?
Thanks!
I encountered the same issue. After investing some time, found the reason. This error is because in chrome settings, you have the Block third-party cookies and site data option enabled.
It can be resolved by disabling this option:
"To find the setting, open Chrome settings, type "Content settings" in the search box, click the Content Settings button, and view the fourth item under Cookies."
Uncheck the box "Block third-party cookies and site data".
Hopefully this helps you in resolving your issue.
The problem is with Google's API console and how it handles creating credentials.
It only seems to work when I access it through the following url
https://developers.google.com/identity/sign-in/web/sign-in#before_you_begin
There is a link that lets you create your app and the OAuth credentials.
When I go to the console and create it through that screen it doesn't seem to work.
After trying and re-create again and test with a fresh app I found out that the URL you add to the Authorized Javascript Origins doesn't always get added.
If everything is good then the url should be available in the credentials page
In my case, I just had to wait a bit for Google to take the origin into account. I cannot tell exactly how long it took. I waited ~30min. I then went to sleep and it was working the following morning.
Edit: Ooops I just realized I was using http:// and not https://. That was the actual problem.
I had the same problem and I searched for 3 days: Resolve " popup_closed_by_user" Go to your console.google go to your API MANAGE : Credentials:modify your credentials:
Authorized Javascript origin (http://localhost:port);
authorized redirect URI(http://localhost:port/auth/google/callback);
Example:|| Authorized Javascript origin (http://localhost:4200);
authorized redirect URI (http://localhost:4200/auth/google/callback)