How to use the Google Calendar API from a Raspberry Pi without a keyboard? - raspberry-pi

Can we get credentials for the Google Calendar API on different devices?
We are using the Google Calendar API on the Raspberry Pi with the following steps as a reference.
https://developers.google.com/calendar/quickstart/python
We have generated the credentials by operating in the following steps
We chose TVs and Limited Input devices as the application type and then downloaded the JSON file.
Credentials > Create credentials > OAuth Client ID
https://console.developers.google.com/apis/credentials
Our Raspberry Pi does not have a keyboard and display.
We note the URL displayed in "Please visit this URL to authorize this application" via ssh.
We access the URL from the PC browser and note the authentication code after tying it to the calendar.
To "Enter the authorization code" we enter it.
It works as we expect.
But this is difficult for our customers.
Can we do this authentication using a PC or smartphone?
In that case, how do we move the token.pickle from the PC or smartphone to the Raspberry Pi?
Maybe we are thinking too hard.
If there is an easier way, please tell us about it.
We just want to use the Google Calendar API.

If you don't have a G-Suite account use SSH in order to send the tokens
Once you get the token.pickle you won't need to "visit" the URL to authorize the application. Anyway, a refresh token has its restrictions. A refresh token might stop working for one of these reasons:
The user has revoked your app's access.
The refresh token has not been used for six months.
The user changed passwords and the refresh token contains Gmail scopes.
The user account has exceeded a maximum number of granted (live) refresh tokens.
Use a service account instead (G-Suite account only)
The token.pickle is generated the first time. The quickstart you mentioned makes use of the user credentials. However if you want to use just one token along the devices and see a different calendar in every device I strongly recommend you to use a service account and enable the domain-wide delegation in order to impersonate the user's calendar.
To do so:
Create a service account
Enable the domain-wide delegation
Impersonate the user in order to see the desired calendar (using Python)
Reference
Refresh token expiration
Creating a service account

Related

Why should I use One tap sign in over Chrome's Credential Management API

Am a bit confused about the One tap sign in that was announced by google earlier this year. Our application already users Credential Management API in Chrome, which essentially provides the user with login options based on the credentials that user has saved for our site on previous visit (passwords that are saved in chrome). When I read the documentation for One tap sign in, it promises to do the same thing, but using Google's client api id. Our application has its own ID provider with our own database of user name and passwords, from the documentation it looks like One Tap sign in does not support custom ID providers. Can anyone shed more light on this, why would I use one against the other?
Thanks
Karthik
I see two major differences:
One Tap is passwordless - it uses a token based login that never exposes the user's password. Chrome Credential Management API stores and retrieves actual passwords in Chrome's password store.
One Tap is purely web based - Chrome Credential Management API relies on Chrome's specific implementation. One Tap is a purely web based workflow so it will work across browsers.
One Tap is a much better long term login solution in my opinion. The Credential Management API is experimental and currently only supported in Chrome.
https://developer.mozilla.org/en-US/docs/Web/API/Credential_Management_API#Browser_compatibility
I lead product development at Google for the one-tap/auto sign-in library, we designed it such that the library includes the Credential Management API and extends to provide assistance in account creation, secure passwordless, and cross-browsers support.
In particular, if you make a request for existing credentials with code like this:
googleyolo.retrieve({
supportedAuthMethods: [
"https://accounts.google.com",
"googleyolo://id-and-password"
],
supportedIdTokenProviders: [
{ uri: "https://accounts.google.com", clientId: "CLIENT_ID" }
]
});
then any saved username/passwords from the Credential Management API will be returned (in browsers supporting the API) along with token data for Google Accounts. The one-tap/auto sign-in JavaScript library wraps the Credential Management API for credential retrieval.
Furthermore, the library provides a googleyolo.hint method to show an email selector for one-tap selection of a verified email address to assist in new account creation, or to link to an existing account, and then be auto signed-in next time with token instead of password, across all browsers, so long as the same Google Account is active.
I'd suggest using the one-tap/auto sign-in library and consuming tokens as well as passwords in order to get assisted sign-up, keep existing users signed-in automatically, and provide functionality even if the browser does not support the Credential Management API.
As for the question about using your own database of username / password, the hope with this library is you could implement the ability to create accounts and auto sign-in to these and existing accounts with an OpenID Connect ID tokens representing the user's identity. With the one-tap / auto sign-in UX, these are not only much more usable, but far more secure then passwords and mitigate creation of weak/re-used passwords. Please consider this or, even better, a hosted auth solution like Firebase Auth or Auth0 and include the one-tap UX in the frontend UI.

Identity Server 3 - Silent sign-in / sign in without login page. Including single sign on

I have come across a number of articles that discuss a similar matter but I cannot find a definitive answer.
My company would like to begin using Identity Server 3, however one of the requirements is to be able to authenticate an external user without them having to manually enter their credentials.
This must be capable of providing single sign on capabilities also as we have 3 different systems and our users should only have to sign in once.
Essentially, the external user has their own CRM.
The CRM holds their username and password for our software.
They then click a button in their CRM to launch our application
This redirects them to our website with a payload containing their credentials
We call a web service to authenticate the user
It is fundamental that we do not change this process for our partners.
Can I implement a custom service provider to provide the authentication or is there some other way of achieving this? If so, could you point me in the right direction for how this can be done?
Many thanks
Craig
I would assume that you'd create a mechanism for their CRM to get a token at the time the client logs into their site and then have them send that token via url to your callback page. This would use the machine-to-machine type grant, or the client-credentials flow. Then that page could validate the token and log the user in. There would have to be some sort of unique identifier between the two systems like email or something. Just an idea.

OAuth - what to store on disk

TL;DR When using google oauth on desktop app, what to save on disk to avoid repeated sign in? Save the google user id? or the token? or an session id?
I'm creating an little desktop app, whitch must authenticate to my REST API server. I'm using google oauth2 for that.
The idea is, that when the desktop app will be authentivated, it generates some data that will be send to my server. The server will store the data with the google user id received from https://www.googleapis.com/userinfo/v2/me.
On the first run of the desktop app, it will open the default browser, with and url for my server and start an local http server. then:
my server will redirect the browser to google (with the clientid, secret, etc.)
user logs in and it will be redirected back to the server with the oauth code
server uses the code to get the token, and then the user profile and stores the token and the profile in db, then redirects the browser to localhost with an paramerer
the desktop app catches the parameter and stores it in an file on the disk
next time the desktop app will start it only reads the file for the parameter to send the generated data with it to my server
my question is: what the parameter should be? the google user id? the oauth token? an generated session id for this desktop app? or something else?
when it will be the google user id, it can conveniently sent the data with the user id and the rest server will just store it in db as is. but I don't think it's safe
when it will be the token, the rest server has to with every request also get the user profile from google with the token. and imho sending the token with every request isn't safe either
generating an session id means to store it with the user and the token on the server and the desktop app will just store it and send it with every request. but I don't know if it's safe to do that
As it's normally the case in software development you have a couple of options depending on requirements.
The mandatory requirement is that your client (desktop) application needs to send something to your REST API so that the API can perform up to two decisions:
Decide who the user is.
Decide if the user is authorized to perform the currently requested action.
The second step may not be applicable if all authenticated users have access to exactly the same set of actions so I'll cover both scenarios.
Also note that, for the first step, sending the Google user ID is not a valid option as that information can be obtained by other parties and does not ensure that the user did authenticate to use your application.
Option 1 - Authentication without fine-grained authorization
Either always sending the id_token or exchanging that token with your custom session identifier both meet the previous requirement, because the id_token contains an audience that clearly indicates the user authenticated to use your application and the session identifier is generated by your application so it can also ensure that. The requests to your API need to use HTTPS, otherwise it will be too easy for the token or session ID to be captured by an attacker.
If you go with the id_token alternative you need to take in consideration that the token will expire; for this, a few options again:
repeat the authentication process another time; if the user still has a session it will indeed be quicker, but you still have to open a browser, local server and repeat the whole steps.
request offline_access when doing the first authentication.
With the last option you should get a refresh token that would allow for your application to have a way to identify the user even after the first id_token expires. I say should, because Google seems to do things a bit different than the specification, for example, the way to obtain the refresh token is by providing access_type=offline instead of the offline_access from OpenID Connect.
Personally, I would go with the session identifier as you'll have more control over lifetime and it may also be simpler.
Option 2 - Authentication + fine-grained authorization
If you need a fine-grained authorization system for your REST API then the best approach would be to authenticate your users with Google, but then have an OAuth 2.0 compliant authorization server that would issue access tokens specific for your API.
For the authorization server implementation, you could either:
Implement it yourself or leverage open source components
⤷ may be time consuming, complex and mitigation of security risks would all fall on you
Use a third-party OAuth 2.0 as a servive authorization provider like Auth0
⤷ easy to get started, depending on amount of usage (the free plan on Auth0 goes up to 7000 users) it will cost you money instead of time
Disclosure: I work at Auth0.
There should be no problem sending the access_token with every request since they are created for that purpose and are thus short lived. You can use the Google Authorization Server endpoint to verify a token instead of using it to do a request for a users profile.
If you're only relying on Google for authentication, here's how your workflow can look:
the client (desktop application, in your case) retrieves the
Google id_token following the user's log in, and then sends it to
the server
the server validates the integrity of said token and extracts the user's profile data; this could mean a simple GET on Google's endpoint to verify this token: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
On subsequent requests, nothing should change really, except that the user's login process will be automated (since he's given permissions & all), and thus much faster. #danielx is right, there's no problem with sending the token each and every time.

Can Google Sign-in be used with Touch ID

Can Google Sign-In be used on an iPhone app in conjunction with Touch ID? If so, how? I cannot find any examples of this being done or talked about online.
Apps can incorporate TouchID as a means to locally authenticate a user.
Basically, the TouchID system can be queried and will let you access items in a keychain or do a simple one-off authentication.
If you stored Google account credentials in a local keychain, you could use TouchID to unlock the local keychain item, and then pass that item to a Google service for Google's authentication.
The keychain item in question (a password) would have to be enter manually at least once by the user (and at that point, it is probably more straightforward to just request an reusable authentication token from Google).
TouchID is entirely a local system, no fingerprint data is ever exposed to third party developers or pushed to a network, so Google couldn't store a fingerprint in their servers and allow direct authentication against their services using TouchID.
Here's the framework reference for Local Authentication:
https://developer.apple.com/library/ios/documentation/LocalAuthentication/Reference/LocalAuthentication_Framework/index.html
The Local Authentication framework is best suited for either confirming a logged in user in an app where the user may be logged in between many sessions (such as for a purchase in a shopping app) or local authentication for local documents (such as for password protected note taking apps).

Outlook.com REST APIs - getting a token without dynamically sign-in

Use-case: Emails to be sent from a web-application upon an event, as someuser#somedomain.com via MS Exchange or Outlook.com, using the RESTful APIs exposed by Outlook.com. Only HTTP access allowed (=> no SMTP/IMAP).
All documentation seems to mention that the app has to forward users to MSOnline, sign-in and then use the authorization code sent back by MS online.
But, this won't work for a background task (=> no sign-in possible!) where a pre-built token(with some predefined scope) is necessary so that Outlook.com can be accessed via APIs to send mail as someuser#somedomain.com.
Any hints/pointers to how it could be done? Basically, automated authentication without explicitly signing in as 'someuser#somedomain.com' on the MS Online login page.
I did not find M$ documentation regarding Outlook REST APIs to be of any great help and found it to be pretty difficult to navigate/understand. :(
Thanks!
At some point you will have to have the user sign in to grant access to your app. So you would need to have some sort of user-facing web front end where they can do this. Once they have signed in and you've obtained an access token/refresh token, your background app should be able to use those tokens silently, without user interaction, at least until the user either revokes access or the refresh token expires.
Currently Azure (which provides the login/token functionality) does expire the refresh tokens after some time (90 days), at which point the user must sign in again to grant your app continued access.