7

I'm trying to set up Google OAuth with my iOS app and Rails web app. I have 2 separate clients (with of course different client IDs, but with the same prefix) set up in the API Console. One for the iOS app, and the other for the web app (which also has a client_secret. I want to use the AppAuth SDK on iOS to get the user's auth code, then send that to my web app, which will then perform the exchange for the access token.

First of all, does this sound like a reasonable thing to do, or is it not possible to split the transaction across clients like that?

My first try was to just take the auth code and perform the exchange, but that failed with the missing_code_verifier invalid_grant error, so I also passed the same code_verifier that AppAuth used to get the auth code to my server, and that fixed that error. First of all, is it necessary to pass this code verifier to the server? Seems a little strange.

Now though, it fails with the unauthorized_client error. My web app is making a request like this:

{
  "grant_type"=>"authorization_code",
  "code"=>"4/XYZ...",
  "client_id"=>"WEB_APP_CLIENT_ID_HERE.apps.googleusercontent.com", 
  "client_secret"=>"WEB_APP_CLIENT_SECRET_HERE", 
  "redirect_uri"=>"https://www.myapp.com/oauth_callback", 
  "parse"=>"json",
  "code_verifier"=>"CODE_VERIFIER_STRING_HERE"
}

Looking at posts like:

it looks like the redirect_uri might be an issue here. My AppAuth config on iOS has the redirect URI set as com.googleusercontent.apps.iOS_CLIENT_ID_HERE, and the Info.plist URL scheme too. The web app's "Authorized redirect URIs" section in the API Console has a bunch of web URLs, and I added the com.google... to it as well. Is this config incorrect? Is the redirect_uri important when doing cross-client auth?

Any help is greatly appreciated! All my trial-and-error have had no fruition so far :(

Community
  • 1
  • 1
quantum
  • 1,400
  • 6
  • 21
  • 34
  • to my knowledge cross client only works with android and possibly ios. I have never seen it working with web or native. Have you seen anything in the documentation stating that it should work? – Linda Lawton - DaImTo Feb 08 '17 at 08:24
  • That's a great point. I've so far not seen anything that say it _does_ or _does not_ work on iOS + web app, but I have seen documentation that it works on Android + web app. – quantum Feb 08 '17 at 15:10
  • One point I'd like to clarify - do you intend to retrieve tokens for _both_ your iOS client and server? Or will you be using the tokens from your backend only? – iainmcgin Feb 13 '17 at 18:31
  • I'll be using the tokens from just the backend only. The backend will use the token for things like email, name, etc., and return that to the client. – quantum Feb 13 '17 at 23:39

1 Answers1

7

I am the lead maintainer of AppAuth, and work on the Google Identity Platform; hopefully I can help.

I want to use the AppAuth SDK on iOS to get the user's auth code, then send that to my web app, which will then perform the exchange for the access token.

First of all, does this sound like a reasonable thing to do, or is it not possible to split the transaction across clients like that?

Exchanging the code on your server sounds reasonable, however I think the configuration you are using is possibly incorrect. If you are requesting a code for exchange on your server, use the server's client id in the request to the authorization server. From your description it sounds like your authorization server request is sending your iOS client ID, and you are then doing the exchange with your server client ID, and I believe this is why you are seeing an "unauthorized_client" error.

This is not terribly well documented, apologies for that. It is alluded to in this section of the documentation on "offline access", though it talks about it purely in terms of Android usage via GoogleApiClient.

is it necessary to pass this code verifier to the server? Seems a little strange.

The intention behind PKCE is to ensure that the entity making the authorization request is the same as the entity making the code exchange request. The code_verifier should not leave the device under normal circumstances.

However, it is not necessary to use PKCE if you are exchanging your code using a client secret controlled by your backend; you can disable PKCE in AppAuth for this scenario.

Community
  • 1
  • 1
iainmcgin
  • 2,691
  • 1
  • 18
  • 24
  • 1
    Thank you for your response Iain! So I am *indeed* passing my iOS client ID to get the auth code, then the server's client ID to exchange that auth code for the token. You're saying that I should use the server's client ID for both, and that the iOS client ID would basically be unused? If so, can I configure AppAuth using the server's client ID and secret? (The iOS client doesn't have a secret) – quantum Feb 13 '17 at 23:58
  • 1
    If you're not using the tokens from your iOS app directly, then you don't need that client ID, just use the server's client ID and send the code to your server for exchange. You *could* also do the token exchange on the client using the client secret, but I strongly recommend you don't do this. Client secrets embedded inside apps are not "secret", they can be trivially extracted from any app. Let your server do it instead, where you can keep the secret safe. – iainmcgin Feb 14 '17 at 05:00
  • Oh I see, so I don't need the server's client secret to hit the authorization server, only for the code exchange (which yes definitely will be performed on the server). And the redirect URI passed into AppAuth should still be the com.googleusercontent... one right? My server is set up to only allow my web URL. – quantum Feb 14 '17 at 16:09
  • 1
    Follow up question, Iain, my AppAuth instance is configured to use `com.googleusercontent.apps.SERVER_CLIENT_ID:/oauthredirect` as the `redirect_uri`, but it's saying "Custom scheme URIs are not allowed for 'WEB' client type" when the Safari view controller opens to perform the auth. Do you know why this is happening? – quantum Feb 15 '17 at 19:10
  • I get the same error. It was working fine about weeks ago. But suddenly not work anymore. – Damon Feb 25 '17 at 08:20
  • I had followed up on this issue with @quantum offline - it is true that web client types don't allow custom schemes. If one is only authorizing a backend, it is simpler to just run the entire authorization flow in the browser and not use AppAuth. If you are only authorizing your app and not a backend, AppAuth with an iOS client type will work fine. If you wish to authorize both, this becomes trickier - The Google Sign-in SDK supports this, but uses an undocumented, non OAuth2 standard mechanism to retrieve a code for both the client and server simultaneously. – iainmcgin Feb 26 '17 at 22:23
  • We're now facing the same error . We fetch server authcode in client using server client id . Then passing this authcode to server . We use the same method in iOS , Android and web . However , now we are getting an error " Custom scheme URIs are not allowed for 'WEB' client type " . How can we solve this ? Any other solutions ? @iainmcgin – wlz Mar 01 '17 at 02:34
  • @wlz are you saying this used to work, but no longer works? – iainmcgin Mar 07 '17 at 04:55