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.
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.
I'm developing a custom passwordless auth to sign into a Cognito user pool. I will describe what I'm trying to implement in case anything is silly. I want a user to enter their email address, then receive a magic login link via email, and when they click on that be taken back to the site and be logged in.
This uses custom auth lambda functions to define/create a challenge with a time based password and send it to the user in an email. I am having a couple of problems:
Problem 1)
When the user returns with the code they might not be in the same browser/device and certainly won't be in the same tab so they don't have the session, meaning I need to call cognitoUser.initiateAuth again. This goes through the define/create challenge lambdas again so a second email gets sent even though at this point the user is coming from the email link so already has the code. Note: the session id is not available in the event object when the challenge is created, also I've read these sessions only last 3 minutes and my time based passwords will last ~15minutes, so I don't think I can include the session id in the email.
Problem 2)
You can login from a few places (browser, android app, etc) and I would like to be able to include the url or at least protocol as a parameter to control what gets sent in the email, e.g. if you entered your email address in the android app then the email you get would be myapp://login?code=xxx and if you did it on the web it would be https://example.com/login?code=xxx
It seems like I would be able to implement both of these to work properly if only I could find some way to send custom metadata through to the DefineChallenge and CreateChallenge lambda such that it would appear in the event object. I thought adding ValidationData to the AuthenticationDetails object would do this, but that information doesn't appear in the event object in the Lambda fns.
The workaround I've found is to create a new client id for every situation - one for initiating auth, one for redeeming token, and repeat for each different protocol. But that is a lot of client ids quickly - a pain to mantain and clumsy.
So tl;dr is: I want to send custom metadata from my cognitoUser.initiateAuth(...) call in JS and have it available in my Define/Create Challenge lambda fns.
You can split the authentication process into multiple custom auth challenges. This allows custom auth state to be supplied via the challenge response as client metadata.
Auth session state must be persisted in a database in order to be shared between devices.
Your custom login flow will probably have two challenge steps: the first prompts for auth type and the second prompts for the secret code. The action taken by the "Create Auth Challenge" Lambda will depend on the auth type. If the auth type is "Email" then the secret code and magic link are generated, stored in DynamoDB and emailed. If the auth type is "MagicLink" then the secret is loaded from DynamoDB. Clicking on a Magic link will initiate a new auth session and automatically supply all the challenge answers.
There are a few other things to consider:
Your magic link needs to encapsulate the Cognito username as well as the one-time secret and probably some other session id that is used as a key in dynamodb.
You probably should not put app-specific links into your emails. Instead associate your domain with your app and/or leverage the redirect URI parameter of your web-based login page.
You can also access custom Cognito user attributes from the Lambda function which can be used to indicate user login preferences (eg Email vs SMS for login codes).
I need to send timeline item to particular subscribed user using Mirror API. I have the user's email id. How can I achive this?
Thanks
Update:
I have GDK app, companion app(which runs on Android mobile device) and Mirror API app. Both GDK app and companion paired via Bluetooth. My use case is I have to send timeline item to uesr if he reached particular location. We are using ibeacon to check user's location. When user reached that particular area, companion app detect it(via bluetooth) and send request to mirror app then mirror app will add timeline item to user's glass. Here my question is how to add the timeline item to one particular user?(not to all subscribed users) And what parameter should I pass to mirror app from companion app?(I was thinking to send the user's email id)
The user will have needed to log into your service using OAuth2 and have granted specific permission for you to access their timeline using the role https://www.googleapis.com/auth/glass.timeline. You should request "offline" access so you will receive both an auth token and a refresh token, which you can use to get a new auth token after an hour.
You will need this auth token when you send a card to the timeline, which also serves as an identifier in this case. Having their email id is not enough, and you don't need it.
See https://developers.google.com/glass/develop/mirror/authorization for some code samples and details.
Update:
So it sounds like you have the following overall work flow:
User creates an account on your website (which is where the Mirror API app is hosted). As part of this, they authorize access to their Glass and either give you their email address or authorize you to get it via Google's API.
You'll store this information (auth_token and refresh_token) in a data store somewhere, indexed against their email address.
They will also install your app on their phone, and it has access to the email address as well.
When the mobile app detects an ibeacon marker it is interested in, it connects to your web service and sends the email address and location.
Your web service looks up the email address, gets the access token to authenticate the connection to the Mirror service, and sends a message to Glass with the location information.
This is a generally reasonable workflow, but there are a couple of important points to make:
The Mirror API is well tuned to sending things to just one person at a time. You sound worried about sending bulk results, but as long as you use the auth token for just one user, it will send it to just that user.
You're using the email address as an index to the entire user account. While this is simple to implement, this is not the best solution, since it means that anyone who has a person's email address and the URL for the endpoint of your service can fake locations. You may consider this an acceptable risk given how you're using the location information (sending it back to the user), but you need to think about how the service could be misused.
You can mitigate the risk in a couple of potential ways:
Instead of an easily guessable email address, you can create and use some other userid which the user will need to enter when they first setup the companion app.
The first time (and only the first time) the app wants to connect to the service, it creates and sends a random secret string which it will use as a password and the web service could store this random string. Afterwards, the companion app would need to send this string along with the email address.
Depending on your needs, you could cut out the webapp completely and have the companion app use the Mirror API directly. This would leave the auth tokens on the phone and would greatly reduce the potential chance to have someone spoof your user. It does have a significant downside - although you can use it to send cards to Glass, it becomes more difficult to get responses from Glass back to the companion device.
As I understand your question and comments above, your user has already authenticated with your Mirror API based application, so you already have the required credentials (auth/refresh tokens). Your companion Android application detects a condition (user in a particular area) and sends a request to your remote endpoint in your Mirror API based application.
The companion app, when sending the request to the remote endpoint, needs to send a common piece of information that can be used to identify that user in your Mirror API app. In this case, you're saying you're sending the users email id.
To send a timeline card to only that particular user, I would take the email id that the companion application has sent, query your database to return the credentials that you saved when the user authenticated originally with your Mirror API based app and then use that to create an authenticated Mirror API request that inserts the timeline item for only that user. I don't know what your Mirror API app is written in, but a basic example in Python might take the following form:
# You sent along the email address
userid = notification['MyCompEmailId']
# set timeline card body
timelinecard_body = {
'notification': {'level': 'DEFAULT'},
'text': "You found a beacon!",
'menuItems': [{'action': 'DELETE'}]
}
# Look up the user in our database and
# get their credentials
#
# _credentials_for_user() basically does a "WHERE userid = 'something'" query
user_credentials = _credentials_for_user(userid).get()
# Create a Mirror API service with some credentials.
authed_mirror_service = build('mirror', 'v1', http=user_credentials.authorize(httplib2.Http()))
# Send a timeline card
authed_mirror_service.timeline().insert(body=timelinecard_body).execute()
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.
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.