Re: [OAUTH-WG] OAuth2/OIDC for client-server mobile app

John Bradley <ve7jtb@ve7jtb.com> Fri, 27 January 2017 16:24 UTC

Return-Path: <ve7jtb@ve7jtb.com>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 5ED24129686 for <oauth@ietfa.amsl.com>; Fri, 27 Jan 2017 08:24:38 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.6
X-Spam-Level:
X-Spam-Status: No, score=-2.6 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=ve7jtb-com.20150623.gappssmtp.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id a1VY6ghVdz0h for <oauth@ietfa.amsl.com>; Fri, 27 Jan 2017 08:24:35 -0800 (PST)
Received: from mail-io0-x233.google.com (mail-io0-x233.google.com [IPv6:2607:f8b0:4001:c06::233]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id C06B4129683 for <oauth@ietf.org>; Fri, 27 Jan 2017 08:24:35 -0800 (PST)
Received: by mail-io0-x233.google.com with SMTP id j18so64202697ioe.2 for <oauth@ietf.org>; Fri, 27 Jan 2017 08:24:35 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ve7jtb-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=KZvXu5YlpGjiZxlvb6rHBeFiHLScx7IkjXzooDDIGqQ=; b=PiShZeXbkCAJ0WtJS+1HUsf3Zi/89Fk6bNXfSkgEyTosguKGiJZik3w63J6jkV8Tp6 NO9fMBmW06kPwCS/d2d1+/08dDGemrnNJ+nWCPAFn88fwoOYjkq8f0UgpXOcBL1yPRPb YKB9u351uK015DX3KXBvPCAVOwTvK/LNZP/gUW/u2kyjOuzjESxC6QDLY159UM/Kfbi2 0flXsN6A1QpSPYmQoquQ/mnNKQmupxRePAfU3mZX+lCdAUitCioh3PsZJgnGv5awgaDO s1nmWsmxz4TUiXtm6wmKVxQDpZaMBQYXmHgbo8HHu/bV4S8XhPzB4ph0clvwleScQyTV 8M3g==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=KZvXu5YlpGjiZxlvb6rHBeFiHLScx7IkjXzooDDIGqQ=; b=QK3kbMaPOXi6/LMvHGuDXtyUFv5NmbNcz9GdfN+RDHq8PKJ5syoGnmfHT+OPt5rnW7 1nKK2dUb9TX6oduwCXzO3BOXUjGaUu+4vNNVBiQiruAecJvZxBbVcBFSZERSp+2Puun6 chVlkZwnerpdqb3OY4Uif3tfe4/wuLB2BVZ0lu3Sybh3NFVCAmlCFjWUoj+c3A8MsgNj DTA5uxNej7O4T4TRU+jYFAx7Yisi6mFyreAJQMRHKvHngwYFTxfiew62HKzWcElTrPan 4VGEdcIzfnQwjldFT4OCLMdXXRBw57jnLGGlLT3yCPu0ttoC1RgZM3IIrND1ifiBTb8N lJ5A==
X-Gm-Message-State: AIkVDXKuWKoBrf4qP7tNVRQnQRKL+zeui0uoM++sZqagjDw0cu0t3Q6yecBsmTfYrOjV4iSFcd6DaqyTvBu5/m7o
X-Received: by 10.107.21.196 with SMTP id 187mr7581309iov.105.1485534274769; Fri, 27 Jan 2017 08:24:34 -0800 (PST)
MIME-Version: 1.0
Received: by 10.79.150.207 with HTTP; Fri, 27 Jan 2017 08:24:34 -0800 (PST)
X-Originating-IP: [2001:569:7128:2400:f1f4:1af4:75b6:921a]
Received: by 10.79.150.207 with HTTP; Fri, 27 Jan 2017 08:24:34 -0800 (PST)
In-Reply-To: <b9d02304725cc8e646cb68b682809328@nleyten.com>
References: <ffc794a133b4b5fb341a0590c6848034@nleyten.com> <5889010c.06d0620a.31d79.5dd8@mx.google.com> <CA+k3eCQ69_+7JEZN30OpOwfW-cy1Dmu6-K84geLLvrjWxpt=7A@mail.gmail.com> <823CE48E-D778-4704-B13D-B6C302ED14D6@oracle.com> <093116990b28d9837f42a7477fc09d80@nleyten.com> <CAANoGhKON-a22CjHTGe3AsSGR=epFZ_YLpKSt9DzrcZ1fY6mPA@mail.gmail.com> <be34721f2dbd38434edadcef5658131a@nleyten.com> <CAANoGh+YdPhvpNfPcWcQVKF1iO+jdrtPMVRRiTp2+GUq2LCD4A@mail.gmail.com> <b9d02304725cc8e646cb68b682809328@nleyten.com>
From: John Bradley <ve7jtb@ve7jtb.com>
Date: Fri, 27 Jan 2017 13:24:34 -0300
Message-ID: <CAANoGhJ0ojaEV8FNvtuOhyRMMeX6rp3sieyvqdRhoU-EDo3hFw@mail.gmail.com>
To: Dario Teixeira <dario.teixeira@nleyten.com>
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha-256"; boundary="001a1148d54ac546ae054715e6e3"
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/8Sr21Q2X5UtqWi3_HOc7MfPsN0I>
Cc: IETF oauth WG <oauth@ietf.org>
Subject: Re: [OAUTH-WG] OAuth2/OIDC for client-server mobile app
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.17
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/oauth/>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 27 Jan 2017 16:24:38 -0000

If you are protecting your API with OAuth in my recommendation there are
two Authorization and token endpoints.  One set run by Google (as an
example) for authentication and issuing a access token for the Google
User_info endpoint, and one set run by you to issue a access token for your
resource server to your native app.

I don't think Justin is recommending using the id_token directly as an
access token for your resource server.  I think he is recommending a
internists step where it is exchanged for an access token.

Our recommendations are based on the assumption that the end state is your
app having an access token for your rest API.

If that is not what you are trying to do then we may be talking at cross
purposes.

I don't think you understand app Auth by your description.

The NA makes a request to the authorization endpoint of your OAuth server
via a view controller or custom tab, that contains a PKCE code_challange.

Your Authorization server then performs whatever authentication it wants to
in that tab.  It could do openid connect to Google, collect a password via
Web form or authenticate via SAML to Azure or a enterprise IDP the choice
is yours because we are logicly decoupling the two steps.

After authentication your Authorization endpoint returns the user to the
app via a claimed URI or custom scheme redirect with a code.
Your native app exchanges that code and the PKCE verifier for a access and
refresh token from your token endpoint so it can access your rest API on
your Resource Server.

Your native app only needs to know about your Authorization server and it's
endpoints.   The native app doesn't know how your Authorization server is
authenticating the user(resource owner) as that happens transparently in
the chrome custom tab/Safari view controller.

In my recommendation your native app has one and only one client_id for
your Authorization server and your Authorization server has the client ID
for google, Facebook and others.

In Justin's recommendation your native app would have a client ID for each
IDP that it is using.   How your back end would validate a id_token passed
by your native app that it received from a IDP is currently not part of any
specification.  That is why you have not found it.   It can be done but is
in my opinion a shortcut that leads to implimentation issues down the road.


The Google developer documentation has information on how to validate
id_tokens that they issue when used in Justin's pattern, but it is a bit
Google specific.

John B.


On Jan 27, 2017 3:25 AM, "Dario Teixeira" <dario.teixeira@nleyten.com>
wrote:

Hi,


Justin and I are recommending different approaches.
>

Thanks for the clarification.  To make sure there's no further
confusion, allow me to define the various parties involved in
the exchange:

 * Native App (NA): the native application running on the user's
   phone. This application is written by me.

 * Resource Server (RS): the server application that the NA wishes
   to communicate with. This application is also written by me,
   and offers a RESTful API to the NA.

 * OpenID Provider (OP): a 3rd party organization like Google that
   is able to authenticate users.

 * Authorization Endpoint (AE): a server run by the OP.

 * Token Endpoint (TE): another server run by the OP.

 * User Agent (UA): a browser running on the user's phone.



Justin is recommending that you build a client/relying party for
> each IdP into your native app and pass the results of authentication
> ID_token, Facebook signed request etc to your back end server for
> it to verify and issue some cookie or webkey (probably not OAuth
> token) to your App for accessing your API.
>

To make sure I understood it correctly, here are the steps involved
in Justin's scheme:

 1. The NA asks the UA to show a webpage with links such as "Login
    with Google" or "Login with Facebook".  Clicking on those links
    executes a request to the AE of the corresponding OP.
    The 'redirect_uri' parameter of the request points to the NA.

 2. The user clicks on one of the links shown in the UA.

 3. The AE sends the NA an Authorization Code.

 4. The NA executes a request to the TE of the OP, sending it the
    Authorization Code obtained in step 3. The 'redirect_uri'
    parameter of the request points to the NA.

 5. The TE sends the NA an ID token.

 6. The NA sends the RS this ID token.

 7. The RS validates the ID token by checking its signature against
    a hardcoded list of OP public keys. If valid, it sends back to
    the NA a cookie that can be used in future requests.

It's pretty straightforward, but there's a bunch of corner cases
surrounding expiration of tokens and making sure the list of OP
public keys are synchronised.



My recommendation is that your app do appAuth to your server to get
> a access token for your API.   Your server performs openid connect
> to google, SAML to salesForce or Facebook Connect to Facebook and
> manages verification keys.   If the user is authenticated by the
> IdP it then authorizes your app on the device to access your API.
>

Again, please allow me to describe the various steps involved in
the AppAuth scheme, to make sure we're on the same page:

 1. The NA executes a request to the RS, telling it the user wishes
    to login.  It also sends the RS a secret S to be used later.

 2. The RS replies with a webpage with links such as "Login with
    Google" or "Login with Facebook".  The 'redirect_uri' present
    on those links points towards the RS.

 3. The NA asks the UA to show the webpage it received in step 2.

 4. The user clicks on one of the links shown in the UA.

 5. The AE sends the RS an Authorization Code.

 6. The RS executes a request to the TE of the OP, sending it the
    Authorization Code obtained in step 5. The 'redirect_uri'
    parameter of the request points to the RS.

 7. The TE sends the RS an ID token.

 8. The RS validates the ID token by checking its signature against
    a hardcoded list of OP public keys. It now knows that any
    future requests from the NA with secret S are authentic.

There's an obvious problem with this scheme: there's no way for the
NA to know when and if the authentication was successful.  Did I
miss something, or is this a know problem with the AppAuth scheme?

Thanks again for your attention!
Best regards,
Dario Teixeira