I am trying to use the Google Contacts API and the Python / GDATA client handlers to access Contacts via OAuth 2.0 for users in the domain. I'm ultimately wanting to create a web service to add contacts for users, but the first step is getting this test working.
I can access my own Contacts just fine if I use the default URI. However, when I pass in the email address to construct the URI for another user, I can't seem to access the other user's Contacts. Here is the code that I'm using:
client.GetContacts(uri=client.GetFeedUri(contact_list=userEmail))
A 403 error is returned when I execute this.
gdata.client.RequestError: Server responded with: 403
Your client does not have permission to get URL /m8/feeds/contacts/<userEmail>/full from this server.
Mostly just trying to understand if what I'm attempting here is even possible. In the Email Settings API, for example, you can get authenticated to the domain and pass in a user's email to list their labels, add filters, etc. So, I would anticipate that the Contacts API would work the same, though handled slightly differently, i.e. modifying the URI, instead of just passing in an argument to the client handler. Please let me know if I am wrong in that presumption.
For authorization, I'm getting the details using flow_from_clientsecrets, then getting the token to authorize the ContactsClient for the domain. Again, I can access my own contacts fine, so authorization seems OK, but I can't access other users' contacts.
client = token.authorize(ContactsClient(domain=domain))
Seems like I'm missing something with respect to accessing other users. Is anybody able to assist me over this hump? Here are some things that I've checked / confirmed:
Contacts API is enabled for the project
Scopes have been authorized for the Client ID in the control panel > Manage 3rd party access
I am a Super Admin in the domain.
Thanks for your time!
I figured out the answer here from another post with exceptional detail:
Domain-Wide Access to Google GDATA APIs
You need to use "Service Account" authentication. For some reason, I was thinking that would only work with the newer discovery-based APIs. But, service account access also works for GDATA APIs. I can access all the Contacts for users in the domain now.
Related
I'm trying to connect my website's API and mobile app. I need to authenticate the user with google account but I don't know how to do it.
I created the backend with Django. And I set the endpoint as rest-auth/google/. On the restframework's page, it requires Access Token and Code but honestly I don't get how I can test if it actually works using actual google account.
I want to test from mobile app but I don't understand how and what I need to POST.
Anyone could give me tips?
I would recommend you to use a ready solution like "django-allauth".
If you want to do authentication yourself you might want to read Google's documentation about the topic:
https://developers.google.com/api-client-library/python/
In nutshell you create API credentials:
https://console.cloud.google.com/apis/credentials
Send a user to a link with specific parameters (api-credentials, scope, redirect link etc). Google client can help you to generate it.
A user will login in his account as he would normally do and will give your app permissions to use his information (or won't). After that he will be redirected to the link you specified with GET request with a code as a parameter (or error).
With help of Google client you can exchange the code on a token and then use that token to get information from his profile.
Trying to understand how to use Cognito and API Gateway to secure an API.
Here is what I understand so far from AWS documentation and the Cognito user interface:
Clients
www-public - public facing website
www-admin - administrators website
Resource Servers
Prices - for this simple example the API will provide secured access to this resource.
Scopes
prices.read
prices.write
Again, very simple permissions on the API. Public www users can read prices, administrators can write them.
API Gateway
GET /prices - accessible to authenticated users that can read prices.
POST /prices - only accessible to administrators
Users
Administrators - can update prices via the POST method.
Non-administrators - cannot update prices.
Based on this...
Each client will request the scopes it is interested in. So for the public www site it will request prices.read and for the administration site both prices.read and prices.write.
The API Gateway will use two Cognito Authorisers, one for each HTTP Verb. So the GET method must check the user can read prices and the POST method that they can write prices.
The bit I don't see is how to put all of this together. I can make the clients request scopes but how do they now connect to user permissions?
When the token is generated, where is the functionality that says "Ok, you requested these scopes, now I'm going to check if this user has this permission and give you the right token?"
I understand that scopes ultimately related to the claims that will be returned in the token.For example, requesting the profile scope means that the token will contain certain claims e.g. email, surname etc.
I think based on this that my permissions will ultimately end up being claims that are returned when specific scopes are asked for. The fact that the two clients differ in what they request means that the prices write claim an never be returned to the public www client. It would never issue a token if the prices.write claim was requested.
What I can't see is where this fits in Cognito. There is the option to put users into groups but that is pretty much it. Likewise, there is nothing (that I could see) to relate scopes to claims.
I'm coming from a .Net and Identity Server background. Certainly in the last version of Identity Server I looked at there was a handler method where you would work out which claims to put into a token. I guess this would map into one of the custom handler lambda functions in Cognito. From there this would need to query Cognito and work out what claims to issue?
The final piece of the puzzle is how the API Gateway checks the claims. Can this be done in API Gateway or does the token need to be inspected in the Lambda function I will write to handle the API Gateway request?
Certainly using Identity Server and .Net there was a client library you would use in the API to inspect the claims and redact permissions accordingly. Guessing there is something similar in a Node JS Lambda function?
A few assumptions there as I'm basically in the dark. I think the basics are there but not sure how to connect everything together.
Hoping someone has figured this out.
Using the Reports API, I have made a simple command line app to return users with unused Gmail accounts. I am using the attribute accounts:last_login_time.
I am writing to ask if this parameter includes the user's usage of the Gmail app for Android
I'm concerned that my API call will falsely return users who only check their account via the android app as 'delinquent'.
I think logging to your gmail regardless of medium is still counted as a log-in activity, hence the server will still take note of that. If you want to make sure, login a member test user account using Android Gmail app and make a request using
Login Activity Report:
GET https://www.googleapis.com/admin/reports/v1/activity/users/all/applications/login?customerId=C03az79cb
Check if it returns the time you logged-in.
Try this reference: https://developers.google.com/admin-sdk/reports/v1/reference/usage-ref-appendix-a/users-gmail
You'll want to use the gmail:last-interaction-time to ascertain whether or not an account is delinquent. The reason is that access via IMAP/POP is counted independently of logon: last_logon_time is an accounts property, whereas user activity reports for Gmail tracks access time in general, as well as access times by protocol (POP, IMAP, WebMail). You can, of course, query both accounts & gmail in the same request with a comma-separated list of the appropriate app-name:parameter pairs.
My app got white-listed for using the Ads API.
I was wondering in regarding to the authentication flow.
Say, that I need to retrieve and execute actions via the API on daily tasks ( with no user interaction) , I find the authentication process quite cumbersome.
Is there a way to work with my app access token instead of a user access token?
I want to be able to approve my app only once for each user and then to be able to work with no user interaction.
Can I achieve this?
App access token is not relevant for this case.
I had to work with the user access token.
I followed this doc: https://developers.facebook.com/docs/reference/ads-api/
Eventually , one should use some client side code in order to get a user permissions and then make another request for getting the user token.
So you'll have to call
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=ads_management,offline_access&response_type=code
Get the authentication code and make another call:
https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&client_secret=YOUR_APP_SECRET&code=AUTHORIZATION_CODE
Then you'll get an access token which is valid only for two months, in opposed to what Facebook docs says in here:
https://developers.facebook.com/roadmap/offline-access-removal/
"Ads APIs are special cased to allow collection of statistics offline. PMD partners should use server-side OAuth flow in order to receive a non-expiring token rather than a token that has longer expiration time."
Too bad that the access token is not really valid forever...
According to "Exception 4" in this document , if you have Ads API access you should be able to get a non-expiring token if you use the correct workflow. Following the guidelines outlined here, if you use the server side OAuth flow, to make the following request you should get a non-expiring token:
GET /oauth/access_token?
grant_type=fb_exchange_token&
client_id={app-id}&
client_secret={app-secret}&
fb_exchange_token={short-lived-token}
thx for the feedback regarding the Access token process being cumbersome. Because this is a one to many solution - a single App ID can manage multiple ad accounts, on behalf of multiple people - we need to make calls on behalf of people.
You should be able to get a persistent access token for Ads API. If you are not getting it, please provide exact steps you are following so we can see if there is a bug or you might be missing a step.
Thx.
I am building a app/API that allows user to login with Facebook, Twitter or Google. I am wondering what are the best practices in allowing those user to use the same account to login to the API.
A couple Ideas that I have had is pass the auth token/cookie in a header to the API for every request and use that to authenticate on the backend.
Run my own OAuth setup and make the user authenticate once with the back end to get my OAuth token and use those from then on.
I am doing the same thing and my solution is to match the email addresses that you get from these respective APIs.
For Facebook, you need special permission from the end user to get the email address registered there. You do this by adding &scope=email to the first oauth request.
A disadvantage is that you need to get this permission from the end user and they may decline. Another disadvantage is that users need to use the same email addresses for Google, Facebook and Twitter.
An advantage is that user records are merged automatically, so users can directly access all their data if they logged in the first time through Google, and the second time through Facebook.
Another approach would be to manually merge their data by making them log in to Google when they are already logged in through Facebook. Then you can conclude that they are the same user, even when they use different email addresses for both. But this is a more tedious approach, as you still need to merge the app's user data from both accounts.
Your first solution is exactly the way I do it. As all my rest services are stateless, the access token goes in the header and is parsed by spring security authentication filters on every request. I use a grails sever with the spring-security-oauth plugin. We also run a website which allows for using session cookies for browser based access.