Google Sign In iOS and Web - ios

I'm building a system with a web and a iOS app. The web part require authentication that can be used on the mobile part and vice versa.
I want to add support for google sign in on the web and on the mobile part. For test i've used the code from
https://developers.google.com/identity/sign-in/ios/start-integrating
for iOS and
https://developers.google.com/identity/sign-in/web/
for the web part.
scope are the same on Application and web (email, profile)
Expected flow
User sign in with google and grant access from mobile (or web)
user go to web site (or application)
user sign in with google
no need to grant permission again
What i got
User sign in with google and grant access from mobile
user go to web site
user sign in with google
same permission are asked again
How can i avoid asking permission again? from the documentation (https://developers.google.com/identity/sign-in/web/cross-platform-sign-in)
seems to be possible to obtain the expected flow but in practice i am unable to obtain it. iOS and Web are in the same google developer project.

I've made this work as expected following this guides: https://developers.google.com/identity/protocols/CrossClientAuth
https://developers.google.com/identity/sign-in/ios/offline-access
what you have to do is the following:
first add
[GIDSignIn sharedInstance].serverClientID = #"SERVER_CLIENT_ID";
in your iOS appDelegate. When the user authenticate through the app you can now retrive a token valid for your server_client_id via serverAuthCode attribute of your GIDGoogleUser object.
Send the token to the server and validate it on the token endpoint (/oauth2/v3/token) redirect_uri must be empty while grant_type must be authorization_codeotherwise you will have a 400 response.
Your server is now authenthicate and when the user will log on the website permission will not be asked again.

Related

Was the google API oath scope authorisation breached in the example below?

The goal of the steps below is to create a custom oath client ID which will be used only for my instance of rclone. rclone already is registered as an app with google API with it's own set of client ID credentials, but the recommended way is create another set for the sake of performance.
In the google api developers console I create a new project called my-rclone-project.
Once the project is created I proceed to the OAuth consent screen where I choose the type External. As I proceed to the OAuth consent screen there is a setting paragraps called Scopes for Google APIs. Here I leave the default scopes (email, profile, openid) explicitly not selecting the scopes which would allow access to google drive.
I call the application my-rclone-app and use the defaults.
After that I go to the Credentials screen and do CREARTE CREDENTIALS -> OAuth client ID.
I choose the Desktop app and name the client my-rclone-desktop-client. Finishing this results in the reation of the Client ID and Client secret. Given the scope selected in the OAuth consent screen i would expect that these credentials won't allow the app to ask permision for anything besides what was defined in the scope. So it shouln't be able to ask for permission to access the google drive APIs.
I than proceed to configure the rclone from my pc rclone config. I enter the oauth credentials I created in the step above. During the config process I'm asked to define the scope to use when accessing google drive as if the OAuth consent screen isn't relevant at all. As the config nears it's end, I'm redirected to the browser where the app is requesting to See and download all your Google Drive files. I accept that end end the config with defaults selected.
As I try listing with ./rclone lsd google-drive: I get an error about the drive API not being enabled with a link in the error on how to enable it. Going on that link and enabling it results in ./rclone lsd google-drive: listing the content of my drive.
What is the purpose of having to define an OAuth consent screen and the API scope as a part of it when the app can request an arbitrary scope completly bypassing the scope selected in the OAuth consent screen setup?
Reference: Create a client ID in google API
Why you want to have custom OAuth consent page?
In order for you app to use one of Google's auth servers, your application needs some way to be identified by auth servers and that is where Client ID and Client Secret comes in to play and consent page server as a screen on which you application specific information such as application name, contact info, privacy policy, term of use etc. will be displayed to the user.
What are scopes that you define on consent screen setup?
On consent screen set up you are supposed to include all possible scopes that you application is going to request from Google APIs, but that doesn't mean you app is limited to those scopes only. Scope listed here will be used by Google for application verification purpose and once Google verifies you application, it will no longer display This app isn't verified warning page as long as your app is requesting one of those verified scopes.
Even after verification, if you application completes verification, requesting any scope access which isn't included in this list will still display This app isn't verified warning message.
and clicking on learn more link will open Google Account help page which clearly states once you provide access to application, when you allow third-party apps to access your Google Account, they can copy and save your data on their own servers. Because Google can’t protect the data on another company’s servers, your data may be subject to greater data security and privacy risks.
What is the purpose of having to define an OAuth consent screen and the API scope as a part of it when the app can request an arbitrary scope completely bypassing the scope selected in the OAuth consent screen setup?
The main purpose of the consent screen configuration is to allow app developer to present information about application it's terms and privacy policy during authorization process. And of course not to have warning once application is verified.
Please refer following link to better understand about unverified apps and scope verification:
https://support.google.com/cloud/answer/7454865?hl=en
https://support.google.com/cloud/answer/9110914
https://www.gmass.co/blog/five-annoying-issues-google-oauth-scope-verification/
https://support.google.com/accounts/answer/3466521?p=app_notverified&visit_id=637365968258169095-220403864&rd=2#notverified

Why does Postman require user login for Google oauth?

I'll try to connect to the content api for shopping via API.
I'de tried some different oAuth ways (e.g. "three-step-method" with access key and baerer-token) but for a spezific integration I need the "credentials-oAuth".
Currently I tried as following:
https://accounts.google.com/o/oauth2/v2/auth?
client_id=[my client id]&
scope=https://www.googleapis.com/auth/content&
redirect_uri=[some random request bin -> added in Authorised redirect URIs ]&
response_type=code
If I call this via Postman, I'll be redirected to the login page of Google. But why?
How can I solve this problem?`
BG
David
Shopping API data is private user data. In order for your application to access private user data it must have the permission of the user who owns that data.
We use OAuth2 to do that. The user must consent to your application accessing its data. In the below image the application Google analytics windows is asking the user for permission to access their Google analytics data.
If I call this via Postman, I'll be redirected to the login page of Google. But why?
You are seeing a login screen with Postman is simple the user needs to be logged in before they can grant access to their data.
How can I solve this problem?
You dont as there is no problem the user must login to grant your client application consent to its data. This is working exactly as it should
Service accounts
Update to answer comment Service accounts are special Google accounts that can be used by applications to access Google APIs programmatically via OAuth 2.0. A service account uses an OAuth 2.0 flow that does not require human authorization. Instead, it uses a key file that only your application can access. This guide discusses how to access the Content API for Shopping with service accounts.

Facebook iOS SDK and passport-facebook authentication

I'm trying to implement server facebook authentication using passport-facebook on an iOS Facebook SDK app, and I'm unclear how to setup the passport authentication on the backend.
Basically the iOS client authenticates with Facebook and gets the sessionToken and I want to pass that to the passport-facebook /auth/facebook/callback to verify the session token with FB, and lookup the user from our database through node.js.
Is that the correct way to use passport-facebook, or do I need call /auth/facebook (and what parameters do I need to pass it).
This issue mentions building an app using Facebook iOS SDK and then authenticating on the server, but doesn't mention exactly how to do that.
https://github.com/jaredhanson/passport-facebook/issues/7
I could also write my own custom passport strategy that simply passes the FB session token and I can verify with FB graph API on the server to get the FB user ID and authenticate it's a valid session, as mentioned here:
Design for Facebook authentication in an iOS app that also accesses a secured web service
Check out passport-facebook-token, which is designed to authenticate based on a previously issued token (ie, the one issued to your iOS app).
passport-facebook is designed to do the web-based, redirect flow, which is not typically done from a mobile application.

can an OAuth consumer app expose an API to an iOS app?

I'm creating an app for iOS that consumes an API I've created, which requires authentication and authorization of users. I'm thinking of using OAuth to let the mobile users do this with Facebook. This is an internal API that isn't meant to be exposed to third parties.
Anyway, I'm a little confused about the abilities and limitations of OAuth consumers versus OAuth providers. Basically, I want to implement "Login with Facebook" functionality from the iOS app. It seems to me that this implies that my API should be an OAuth consumer, but the problem with this is that the login flow for a web app assumes a browser -- an NSURLConnection instance isn't going to know what to do with an HTML login page, and even if the redirect to the login page was made to work by prefixing the redirect URI with the fb:// schema, surely the login form is going to pass the authorization token back to the iOS app and not my API?
So my question is: is there a way to implement my API as an OAuth consumer? If not, and I should implement it as an OAuth provider, what does logging in with credentials from another provider like Facebook even mean?
I think things are a bit mixed up:
OAuth is to Authenticate your app against facebook. A user grants
access to his FB account to your app on behalf of him
"Login with FB" is the other way round and is not OAuth: A User
with an FB account is using this data to register AND login to your
app.
The entire flow of the # 2 can be read here.

For a hybrid SSO scenario using the Facebook iOS SDK, what's the best way generating a password/key for our own custom user records?

So my intention is to have a login in my iOS app that allows for either our standard email/pwd registration, or login with Facebook. We are also creating rest services to get application info for a given user, e.g. https://url/getPosts/[userId]?userPwd=foo
I've implemented SSO with fb in a web application before but I have some concerns about the security of authentication in a iOS client scenario. The key difference from what I've done before is that in a web app, I was making a server to server call to Facebook to get the access token so I was reasonably assured that the user was authenticated and the web server made privileged calls to the database. In the iOS case, I have the mobile client app making the Facebook iOS authentication request itself and the server has to somehow trust that this user from the client app is indeed authenticated against the matching user record in our database.
My question is how do I generate a durable and secret unique key from the iOS SDK so that I can create and associate a matching user record in our database for users that authenticate only with Facebook. I want this to be seamless so the user would not have to manually fill out another form, and we would just automatically create this matching user record in our db.
I could insert a record into my own users table when they fbDidLogin with Facebook, using the Facebook Id as the unique identifier, and the fb access token as the pseudo password/key for my own user record. I would have to validate the access token with Facebook to make sure it's valid before saving it as a password for the user (the user would never see this password, it would just be passed by the client app during api calls). That way when the user makes a call to our own rest api via the iPhone app we can authenticate and authorize using this secret/pwd/key.
An alternative that would make this whole question moot is to just handle the authorization logic on the client app, and check that there is a valid fb session before making calls to our own apis which I secure with just a single application-wide secret, but that doesn't seem as secure since getting that one secret gives authorization to data on all users. I'd rather authorize at an individual user level. Is that the right choice? Am I being paranoid about iOS security?
The fb access token expires so that might not seem durable, however if I enable offline access that token won't expire but creates a scarier looking oauth dialog window. An alternative to the access token is to hash the fb Id with an application secret key on the iOS client, and use that as the Facebook user's password in our db. However, that again is a single secret key that could perhaps be reverse compiled from the iOS client app?
Design for Facebook authentication in an iOS app that also accesses a secured web service
This post helped me undesrtand it more. If I am not mistaken, the flow goes like this:
User authenticates in iOS app
iOS app takes auth token, sends it to the rails app
Rails app takes auth token and sends it to graph.facebook.com/?auth_token=XXX to get back the user if authentication was successful.
Rails app takes the user info and matches/creates user in own database table. Sends some kind of authentication key back to iOS app.
iOS app saves the authentication key so it can use it to communicate with the rails app.
Let me know if I am missing anything.
Have you looked at the iOS docs for Single Sign On (SSO)? https://developers.facebook.com/docs/guides/mobile/#ios
You can share an app ID across mobile, canvas and web site and the same user auth works for each environment.
Check out: https://developers.facebook.com/docs/authentication/
Facebook Platform provides a number of ways to use the above OAuth flows in different app types, including Websites, Apps on Facebook.com, Mobile and Desktop Apps.
You just need to insert users Facebook key to your database to know if its authenticated with Facebook. Use OAuth at ios side authenticate user take users secret key send it to your rest web-service and save it with users other info.

Resources