We have
An existing Django backend with Python social auth for signing in with Google, providing web-based application and an API for the mobile app.
An iOS mobile app with GoogleSignIn pod.
Now we would like to allow mobile app users to sign in with Google inside the app, and then authenticate them on the backend, so that they can access their personal data via the app.
So my idea of the algorithm is:
App uses the GoogleSignIn and finally receives
access_token
.App sends this
access_token
to the Backend.Backend verifies this
access_token
, fetches/creates the user, returns somesessionid
to the App.App uses this
sessionid
for further requests.
The problem is with the third step: token verification. I found two ways of verifying:
1. Python social auth flow
As described in the docs:
token = request.GET.get('access_token')
user = request.backend.do_auth(token)
if user:
login(request, user)
return 'OK'
else:
return 'ERROR'
This would be a preferred flow, since it already has all the required steps and is working perfectly with the web app (like, accounts creation, defaults for newly created users, analytics collection, etc.).
But the problem is that the backend and the app use different CLIENT_IDs for the auth. This is due to the limitations in the Google Developers Console: when creating credentials, you need to select whether it will be a web app or an iOS app, and it cannot be both.
I tried to use different client ids (then backend cannot verify), tried to use web id inside the app (then the pod does not work), and tried to use app id inside the web (then the backend cannot verify again).
2. Google API Client Library
Another option is to utilize the way from the Google Sign-In for iOS documentation:
from google.oauth2 import id_token
from google.auth.transport import requests
try:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
userid = idinfo['sub']
except ValueError:
# Invalid token
pass
It worked, but here we're missing all the pipeline provided by social auth (e.g. we need to create a user somehow), and I could not find a proper way of starting the pipeline from the middle, and I'm afraid it would be quite fragile and bug-prone code.
Another problem with this solution is that in reality we also have Signed in with Apple and Sign in with Facebook, and this solution will demand ad-hoc coding for each of these backends, which also bring more mess and unreliability.
3. Webview
Third option would be not to use SDKs in the Swift and just use a web view with the web application, as in the browser.
This solves the problem with the pipeline and client ids.
But it doesn't look native, and some users may suspect phishing attempts (how does it differ from a malicious app trying to steal Google identity by crafting the same-looking form?). Also, I'm not sure it will play nicely with the accounts configured on the device. And it also will require us to open a browser even for signing in with Apple, which looks somewhat awkward. And we're not sure such an app will pass the review.
But, maybe, these all are minor concerns?
⁂
So, what do you think? Is there a fourth option? Or maybe improvements to the options above? How is it solved in your app?