Accessing Firebase DB from Google App Engine - python

I am having trouble accessing Firebase DB from a GAE app. It works fine when running locally, but deployed to GAE (*.appspot.com) I get an unauthorized error back from Firebase. There is likely some obvious thing I missed...
This is the _get_http() function I use. It works fine (after doing gcloud beta auth application-default login)
def _get_http():
_FIREBASE_SCOPES = [
'https://www.googleapis.com/auth/firebase.database',
#'https://www.googleapis.com/auth/userinfo.email'
]
"""Provides an authed http object."""
http = httplib2.Http()
# Use application default credentials to make the Firebase calls
# https://firebase.google.com/docs/reference/rest/database/user-auth
creds = GoogleCredentials.get_application_default().create_scoped(_FIREBASE_SCOPES)
creds.authorize(http)
return http
The error I get back from Firebase is:
{u'error': u'Unauthorized request.'}
The log from GAE looks includes this:
11:14:43.835
Attempting refresh to obtain initial access_token
11:14:44.625
Refreshing due to a 401 (attempt 1/2)
11:14:44.966
Refreshing due to a 401 (attempt 2/2)

Got it! I had commented out 'https://www.googleapis.com/auth/userinfo.email' thinking it was unnecessary. Wrong. Enabling it again, bingo!

Related

Google OAuth error 400: redirect_uri_mismatch in Python

first time using OAuth here and I am stuck. I am building a web app that needs to make authorized calls to the YouTube Data API. I am testing the OAuth flow from my local computer.
I am stuck receiving Error 400: redirect_uri_mismatch when I try to run my Google OAuth flow in Python. The error occurs when I access the link generated by flow.run_console()
Here is my code:
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
client_secrets_file="./client_secret.json"
scopes = ["https://www.googleapis.com/auth/youtube.readonly"]
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
flow.redirect_uri = "http://127.0.0.1:8080" # Authorized in my client ID
credentials = flow.run_console()
This code returns the message:
Please visit this URL to authorize this application: ***google oauth url ***
Enter the authorization code:
Visiting the link results in the following error:
I tried setting the Authorized Redirect URI in my OAuth Client ID to http://127.0.0.1:8080 since I am testing from my local machine. I also set flow.redirect_uri to http://127.0.0.1:8080 in Python. Using http://127.0.0.1:8080 is currently my only option since the front end has not been set up yet.
I expected the code to authorize my request, since the Authorized URI matches the redirect_uri. But I am still receiving the error.
I have had no issues running the flow from Google's OAuth Playground, if that means anything.
Any help is appreciated, thank you.
Thanks for your help everyone. I was able to find a working solution for my issue from referencing this documentation: https://googleapis.github.io/google-api-python-client/docs/oauth.html
Here is my solution:
def get_subscribers(channel_id="Channel_id",
client_secrets_file="Client_secret_file", n=50):
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
flow = Flow.from_client_secrets_file(
client_secrets_file,
scopes=["https://www.googleapis.com/auth/youtube.readonly"])
flow.redirect_uri = "http://localhost"
auth_url, __ = flow.authorization_url(prompt="consent")
print('Please go to this URL: {}'.format(auth_url))
code = input('Enter the authorization code: ')
flow.fetch_token(code=code)
youtube = googleapiclient.discovery.build(
"youtube", "v3", credentials=flow.credentials
)
request = youtube.subscriptions().list(
part="subscriberSnippet",
forChannelId=channel_id,
maxResults=n,
mySubscribers=True
)
return request.execute()
Change redirect_uri to http://127.0.0.1/ or http://localhost/. I have faced a similar issue before with Google Drive API, and removing the port number worked for me.
The library seems to have a bug.
I know it is not so good but in this case the hack is
flow._OOB_REDIRECT_URI = = "http://127.0.0.1:8080"
are you sure this is definitely your redirect uri? go to your client_secrets.json you downloaded when generating your credentials from the API centre and your redirect uris are in there, http://localhost (NOTE - without the trailing slash!) was specified in mine by default - if it isnt in yours then use the one specified in the json.

Spotipy redirect uri opening on server instead of users browser?

I built a web app using Django and the wrapper for the Spotify api, Spotipy, and deployed it to Heroku. The problem I am facing is that the redirect uri opens on the machine running the code, which in this case is the linux server used by heroku. Because of this, the user never actually sees the page prompting them to authenticate the app and login to their Spotify accounts, resulting in a request timeout from Heroku. This happens when my REDIRECT_URI is set to http://localhost/. I have tried to set the REDIRECT_URI to https://nameofmyapp.herokuapp.com which then resulted in an EOFError from the Spotipy module. I have not been able to find a solution for this. For context, my authentication flow is set up as follows:
def index(request):
cache_handler = spotipy.DjangoSessionCacheHandler(request=request)
auth_manager = spotipy.oauth2.SpotifyOAuth(
env("CLIENT_ID"), env("CLIENT_SECRET"), env("REDIRECT_URI"), scope=env("SCOPE"), cache_handler=cache_handler)
session = spotipy.Spotify(
oauth_manager=auth_manager, requests_session=True)

Google oAuth 2.0 API Authentication Error: Error 400 - redirect_uri_mismatch (does not comply with policy) DJANGO APP

I am trying to get my google authentication working on a Django app that is requesting Gmail and Calendar data. I have set up the oAuth API in the Google developer console and linked it with my project, and I've triple-checked that my redirect URI perfectly matches that in the code (No errors with HTTP vs. HTTPS nor any inconsistencies with the slashes). I made sure that my key, secret key, ClientID, and Client Secret are all configured and identical in my Django app's admin page. I have followed many youtube tutorials and searched other questions on stack overflow but Authentication is still not working. I am getting an Error 400: redirect_uri_mismatch. Even though I have checked many times to confirm that they are the same.
From all the tutorials, I have learned that there are two main origins for this error:
Server sided (can be fixed in the cloud hosting developer console)
Client sided (can be fixed by altering the code)
Both of these errors have their own individualized messages saying what type of mismatch it is.
Mine, however, says this: You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy. \n\nIf you're the app developer, register the redirect URI in the Google Cloud Console.
Here is a photo of the error
[![Google Authentication error message][1]][1]
from django.shortcuts import render, redirect
from django.http import HttpRequest
from google_auth_oauthlib.flow import Flow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from .models import CredentialsModel
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
import os
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
#Scopes are what we should be allowed to access
SCOPES = ['https://mail.google.com/', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'openid']
"""
IF HAVING ISSUES WITH ANON USER:
Make sure you are on 127.0.0.1:8000, not localhost, both from the test-page and
the callback page. For some reason they are treated as different sessions and thus will have
issues maintaining a logged in user
"""
def oauth2callback(request):
activeUser = request.user
#URL is what we need to use for authentication
authorization_response = request.build_absolute_uri()
flow = Flow.from_client_secrets_file(
settings.GOOGLE_OAUTH2_CLIENT_SECRETS_JSON,
scopes=SCOPES,
#This is where we are redirected after authentication
redirect_uri='http://127.0.0.1:8000/google/oauth2callback')
#Now get proper token
flow.fetch_token(authorization_response = authorization_response)
#print(request.user)
#Now save in our database
#print(flow.credentials)
try :
my_credential = CredentialsModel.objects.get(pk = activeUser)
except ObjectDoesNotExist:
CredentialsModel.objects.create(id = activeUser, credential = flow.credentials)
else:
my_credential.credential = flow.credentials
my_credential.save()
return redirect(flow.redirect_uri) #activeUser.get_absolute_url())
[1]: https://i.stack.imgur.com/2HXGP.png
google's documentation is not clear on this part (probably a bug on google's end too):
go to your GCP console, under OAuth consent screen, when the Publishing status is In production, we can still put http://localhost:8080/oauth-authorized/google under the Authorized redirect URIs without triggering the red error message saying Invalid Redirect. However, it doesn't work unless the app is in Testing status.
so in order to test your app at http://127.0.0.1:8000, you need to bring your GCP app to Testing status
hey i was dealing with this problem in ASP.Net MVC,
i think the reason would be the same in php but anyways,
Make sure to copy that url in ur below img to Authorized redirect URIs in OAuth 2.0 Client IDs in Google cloud console.
Check if you are logged in to your google account.
I was using google chrome browser and turns out I was logged out of Gmail as the session expired and when I logged into Gmail and the issue was resolved
In my case, it working in development environment and not in production environment. Enabling API KEY for production resolved the issue.
Copy the url that comes with the error message you get and add it to the authorize redirect uris in your google cloud console
In my case I needed to change my redirect URI from
https://{{my-url}}/google/endpoint
To
https://www.{{my-url}}/google/endpoint

How to delete existing Google OAuth2.0 token (Error 401: deleted_client)

I deleted the credentials I had for a test app on Google Cloud Platform and made new ones. I was trying to solve an issue I was having but unfortunately this introduced a new problem. The issue appears when I'm redirected to the Google sign-in page. I inspected the Google URL, and it would appear that it is trying to use the client ID from my old credentials to sign in. This despite me having updated the client secret JSON file. Could this token be stored in a working directory? And if so how would I find it (I'm using VSCode)??
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(r"client secret location", scopes=scopes)
flow.redirect_uri = 'redirect URL'
authorization_url, state = flow.authorization_url(
access_type='offline',
include_granted_scopes='true'
)
token = flow.fetch_token(authorization_response=authorization_response)
credentials = flow.credentials
Photo of the error from Google
I was having issues because the callback URL for my OAuth client ID (under the credentials tab on Google Cloud Platform) had been typed incorrectly. I went back and corrected it, and then generated a new Client Secret JSON file. Not sure if the latter step was necessary, but the issue was resolved.

401 Unauthorized making REST Call to Azure API App using Bearer token

I created 2 applications in my Azure directory, 1 for my API Server and one for my API client. I am using the Python ADAL Library and can successfully obtain a token using the following code:
tenant_id = "abc123-abc123-abc123"
context = adal.AuthenticationContext('https://login.microsoftonline.com/' + tenant_id)
token = context.acquire_token_with_username_password(
'https://myapiserver.azurewebsites.net/',
'myuser',
'mypassword',
'my_apiclient_client_id'
)
I then try to send a request to my API app using the following method but keep getting 'unauthorized':
at = token['accessToken']
id_token = "Bearer {0}".format(at)
response = requests.get('https://myapiserver.azurewebsites.net/', headers={"Authorization": id_token})
I am able to successfully login using myuser/mypass from the loginurl. I have also given the client app access to the server app in Azure AD.
Although the question was posted a long time ago, I'll try to provide an answer. I stumbled across the question because we had the exact same problem here. We could successfully obtain a token with the adal library but then we were not able to access the resource I obtained the token for.
To make things worse, we sat up a simple console app in .Net, used the exact same parameters, and it was working. We could also copy the token obtained through the .Net app and use it in our Python request and it worked (this one is kind of obvious, but made us confident that the problem was not related to how I assemble the request).
The source of the problem was in the end in the oauth2_client of the adal python package. When I compared the actual HTTP requests sent by the .Net and the python app, a subtle difference was that the python app sent a POST request explicitly asking for api-version=1.0.
POST https://login.microsoftonline.com/common//oauth2/token?api-version=1.0
Once I changed the following line in oauth2_client.py in the adal library, I could access my resource.
Changed
return urlparse('{}?{}'.format(self._token_endpoint, urlencode(parameters)))
in the method _create_token_url, to
return urlparse(self._token_endpoint)
We are working on a pull request to patch the library in github.
For the current release of Azure Python SDK, it support authentication with a service principal. It does not support authentication using an ADAL library yet. Maybe it will in future releases.
See https://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagement.html#authentication for details.
See also Azure Active Directory Authentication Libraries for the platforms ADAL is available on.
#Derek,
Could you set your Issue URL on Azure Portal? If I set the wrong Issue URL, I could get the same error with you. It seems that your code is right.
Base on my experience, you need add your application into Azure AD and get a client ID.(I am sure you have done this.) And then you can get the tenant ID and input into Issue URL textbox on Azure portal.
NOTE:
On old portal(manage.windowsazure.com),in the bottom command bar, click View Endpoints, and then copy the Federation Metadata Document URL and download that document or navigate to it in a browser.
Within the root EntityDescriptor element, there should be an entityID attribute of the form https://sts.windows.net/ followed by a GUID specific to your tenant (called a "tenant ID"). Copy this value - it will serve as your Issuer URL. You will configure your application to use this later.
My demo is as following:
import adal
import requests
TenantURL='https://login.microsoftonline.com/*******'
context = adal.AuthenticationContext(TenantURL)
RESOURCE = 'http://wi****.azurewebsites.net'
ClientID='****'
ClientSect='7****'
token_response = context.acquire_token_with_client_credentials(
RESOURCE,
ClientID,
ClientSect
)
access_token = token_response.get('accessToken')
print(access_token)
id_token = "Bearer {0}".format(access_token)
response = requests.get(RESOURCE, headers={"Authorization": id_token})
print(response)
Please try to modified it. Any updates, please let me know.

Categories

Resources