OpenID Connect: Passing authorization between a mobile app and a browser for SSO - what's a secure way to do it?
Asked Answered
E

1

6

I'm not sure there is a "proper" way, but before I just bodge together my own incompatible implementation, perhaps there's something in all the standards that can fit my need?

Here's the situation: Apple has declared that apps on their phones MUST include all standard functionality inside themselves. No more iframes with web content! If you need to show stuff from web, open the system browser (Safari)! Unfortunately we need to display stuff from web, so here we go...

Now, the app requires authentication which the user has done previously. We store whatever tokens we need. When the time comes to open the browser, we don't want to force the user to re-authenticate. We need to somehow pass the access credentials to the browser, and preferably do this securely. Furthermore, the webpage in the browser will need a token obtained from our OpenID Connect server.

Unfortunately, the only point of communication between the app and the browser is the URL, so everything that we give will be there, in plain sight. I know that OAuth was pretty worried about this, so much so that they made it impossible to intercept authentication with just the stuff visible on the screen and instead using things like single-use intermediary codes, backchannels and PKCE.

Unfortunately I cannot see any way to use the default flows "out of the box" to achieve what I need. I can think of modifications to those flows that would do it, but I'm not a security expert so I'd rather go with something standard which is vetted by experts.

Esparto answered 16/6, 2020 at 7:16 Comment(0)
T
3

SCENARIO

It's a good question since many companies want to show existing web content in a secured manner within a mobile app, and to avoid an extra login.

WEB + MOBILE INTEGRATED SOLUTION VIA DISCONNECTED BROWSER?

Ideally what you want to do is pass the mobile app's JWT to the external web content in an HTTP header. iOS APIs such as openURL may not support this however.

You may have to pass a JWT in a query string, in which case I would try to follow a signed request model, though it is not trivial. I have used SalesForce signed requests though not implemented a full solution myself.

  • Mobile app calls an API method at POST /api/encrypt-token
  • API returns an encrypted payload that includes the JWT
  • Mobile app opens a web page at https://mywebapp?token=0a78904cwdu
  • Web UI calls POST /api/decrypt-token to get the JWT
  • Web UI stores the token in memory and uses it to call the API

You will want to prevent raw tokens being written to web server logs. I believe the recommendation for this type pf solution is to use a one time key, as described in the above link. And of course the web session will have some limitations such as silent token renewal not working.

WEB + MOBILE INTEGRATED SOLUTION VIA WKWEBVIEW

In the past I've managed secured web content in a mobile app by making the Web UI get access tokens from the mobile app. This enables an integrated UX and you can use a 'standard as possible' OAuth solution.

  • When the Web UI runs within a mobile app's web views it no longer does its own OAuth handling and instead calls the mobile app to get tokens and trigger logins
  • This means there is a single login across web and mobile views, and the Web View gets all the benefits of mobile user experience, such as secure storage of tokens
  • The Web UI is no longer impacted by things like the web view aggressively dropping cookies

VALID USE OF WEB VIEWS?

Web views are probably not a good long term solution in most cases. I know that Apple are likely to reject apps in 2020 if they use any of these behaviours:

  • Use of UIWebView - the Cordova default - you need to update to WKWebView
  • Delivering an app that is solely a repackaged web site with no mobile views
  • Displaying web content of a dubious nature (ads etc)

I suspect that use of WKWebView used responsibly and justifiably would be accepted. I could be wrong though, so please don't take my word for it.

UPDATE

Out of interest there is a nonce pattern that can be potentially used to shared data between web and mobile apps, though the simpler choice is often just to share data using APIs, and write views multiple times.

Theresita answered 16/6, 2020 at 19:10 Comment(8)
That's the point. If our guys could use WebView, there would be no problem. But as I understand the updated terms and conditions included something along the lines of "all main functionality must be within the app package and cannot be downloaded at runtime. To display external webpages, launch Safari". I don't know the details since I don't work on the app but rather on the backend. Supposedly it was pretty vaguely defined and they scratched their heads for a good long while until deciding that better safe than sorry and ditched the webviews. I'll try to get a link tomorrow.Esparto
To clarify: the app itself is written in HTML/JS so it actually is one big WebView (I think it uses Apache Cordova to run both on Android and iOS). But it is not allowed to open an iframe with an external website. It can only show local resources.Esparto
I see your concern now. Cordova HTML / JS is fine since it gets translated to native views during the compilation process. External web content may be OK in WKWebView controls - though it may depend how large a percentage of your app this comprises. I added some notes to my original answer above.Theresita
It wouldn't be a large percentage, but it certainly would be a part of its "core functionality" and it would involve financial transactions. And yes, they finished moving stuff over to the WKWebView recently, if memory serves me. I don't know if Apple would be willing to let it slide, but we also don't want to take any chances. So an external browser it is.Esparto
The reason we don't want to port the new functionality to the app itself is mostly because of cost/time issues. It already needs to be part of our webpage anyway, so it's more efficient just to make the webpage responsive and point the app at it rather than re-implement the complex bit of coding in the app too. Also it's in active development so changes are expected. Maybe someday we will move it into the app itself, but now we need a faster solution.Esparto
Cool - so it looks like passing the mobile JWT to the external web content is the way to go, but it is a difficult thing you are asking for. I would look into the 'signed request' pattern, as in my updated answer. This is used by quite a few vendor tech stacks such as AWS / SalesForce ...Theresita
This is also the model I'm trying to go with. It's the best I can come up with but it does have one drawback - the single-use code that I pass to the website in an URL is all that is needed to ultimately authenticate. OAuth was very careful to avoid such a situation in their flows, relying in addition either on client authentication or PKCE. I guess it's not a big deal and all in all it's a rather difficult thing to exploit, but... doesn't feel quite right. :)Esparto
@GaryArcher did you solve this? Did the nonce pattern work for you? We have a similar issue and I am looking for a solution.Tangram

© 2022 - 2024 — McMap. All rights reserved.