Organizing a secure channel between a Web app and a Native app - windows

This question is kinda complimentary to "Share credentials between native app and web site", as we aim to share secrets in the opposite direction.
TL;TR: how can we securely share the user's authentication/authorization state from a Web Browser app to a Native Desktop app, so the same user doesn't have to authenticate additionally in the Native app?
TS;WM: We are working on the following architecture: a Web Application (with some HTML front-end UI running inside a Web Browser of user's choice), a Native Desktop Application (implementing a custom protocol handler), a Web API and an OAuth2 service, as on the picture.
Initially, the user is authenticated/authorized in the Web Browser app against the OAuth2 service, using the Authorization Code Grant flow.
Then, the Web Browser content can do one-way talking to the Native app, when the user clicks on our custom protocol-based hyperlinks. Basically, it's done to establish a secure bidirectional back-end communication channel between the two, conducted via the Web API.
We believe that, before acting upon any requests received via a custom protocol link from the Web Browser app, the Native app should first authenticate the user (who is supposed to be the same person using this particular desktop session). We think the Native app should as well use the Authorization Code flow (with PKCE) to obtain an access token for the Web API. Then it should be able to securely verify the origin and integrity of the custom protocol data, using the same Web API.
However, it can be a hindering experience for the user to have to authenticate twice, first in the Web Browser and second in the Native app, both running side-by-side.
Thus, the question: is there a way to pass an OAuth2 access token (or any other authorization bearer) from the Web Browser app to the Native app securely, without compromising the client-side security of this architecture? I.e., so the Native app could call the Web API using the identity from the Web Browser, without having to authenticate the same user first?
Personally, I can't see how we can safely avoid that additional authentication flow. Communication via a custom app protocol is insecure by default, as typically it's just a command line argument the Native app is invoked with. Unlike a TLS channel, it can be intercepted, impersonated etc. We could possibly encrypt the custom protocol data. Still, whatever calls the Native app would have to make to decrypt it (either to a client OS API or some unprotected calls to the Web API), a bad actor/malware might be able to replicate those, too.
Am I missing something? Is there a secure platform-specific solution? The Native Desktop app is an Electron app and is designed to be cross-platform. Most of our users will run this on Windows using any supported browser (including even IE11), but ActiveX or hacking into a running web browser instance is out of question.

The best solution : Single Sign On (SSO) using Custom URL Scheme
When I was checking your question, I remembered the Zoom app that I am using in my office. How it works ?
I have my Gmail account linked to a Zoom account (this is account linkage, which is outside the scope of implementation). When I open Zoom app, I can choose the option to login with Gmail. This opens my browser and take me to Gmail. If I am logged in to Gmail, I am redirected back to a page that asking me to launch Zoom app. How this app launch happen ? The application register a custom URL scheme when app get installed and the final redirect in browser targets this URL. And this URL passes a temporary secret, which Zoom application uses to obtain OAuth tokens. And token obtaining is done independent of the browser, a direct call with SSL to token endpoint of OAuth server.
Well this is Authorization code flow for native applications. And this is how Mobile applications use OAuth. Your main issue, not allowing user to re-login is solved. This is SSO in action.
There is a specification which define best practices around this mechanism. I welcome you to go through RFC8252 - OAuth 2.0 for Native Apps.
Challenge
You need to implement OS specific native code for each application distribution. Windows, Mac and Linux have different implementation support for custom URL scheme.
Advice
PKCE is mandatory (in IETF words SHOULD) for all OAuth grant types. There is this ongoing draft which talks about this. So include PKCE for your implementation too.
With PKCE, the redirect/callback response is protected from stealing. Even some other application intercept the callback, the token request cannot be recreated as the PKCE code_verifer is there.
Also, do not use a custom solution like passing secret through another channel. This will make things complicated when it comes to maintenance. Since this flow already exists in OAuth, you can benefit with libraries and guidance.
-----------------------------------------------------
Update : Protecting Token Request
While the custom URL scheme solves the problem of launching the native application, protecting token request can be challenging. There are several options to consider.
- Bind native application launch with a secret shared from browser
When browser based client launch the native client, it can invoke a custom API to generate a secret. This secret acts like a one time password (OTP). User has to enter this value in native app before it obtain tokens. This is a customization on top of Authorization code flow.
- Dynamic client registration & Dynamic client authentication
Embedding secrets into public clients is discouraged by OAuth specification. But as question owner points out, some malicious app may register itself to receive custom URL response and obtain tokens. In such occasion, PKCE can provide an added layer of security.
But still in an extreme case, if malicious app registers the URL plus use PKCE as the original application, then there can be potential threats.
One option is to allow dynamic client registration at the first time of application launch. Here, installer/distribution can include a secret that used along with DCR.
Also, it is possible to use dynamic client authentication through a dedicated service. Here, the application's token request contains a temporary token issued by a custom service. Custom service obtain a challenge from native application. This may be done through totp or a cryptographic binding based on an embedded secret. Also it is possible to utilize OTP (as mentioned in first note) issued through browser, which needs to be copy pasted manually by end user. Once validated, this service issue a token which correlate to the secret. In the token request, native client sends this token along with call back values. This way we reduce threat vectors even though we increase implementation complexity.
Summary
Use custom URL scheme to launch the native application
Browser app generate a temporary secret shared with a custom service
At native app launch, user should copy the secret to native app UI
Native app exchange this secret with custom service to obtain a token
This second token combined with call back authorization code (issued through custom url scheme) is used to authenticate to token endpoint
Above can be considered as a dynamic client authentication
Value exposed to user can be a hashed secret, hence original value is never exposed to end user or another client
DCR is also an option but embedded secrets are discouraged in OAuth world

As you mentioned, using a custom protocol handler is not a safe way to pass secrets, since another app may handle your protocol and intercept that secret.
If you are imposing a strict constraint that the communication channel between the native app and the web app is initiated from the web app, and that the native app has not previously established a secure channel (e.g. shared secret which could encrypt other secrets), then it is not possible to safely transmit a secret to the native app.
Imagine if this were possible, then PKCE would be redundant in an OAuth 2.0 Code Flow, since the server could have safely transmitted the access token in response to the authorization request, instead of requiring the code_verifier to be provided with the grant when obtaining the access token.

Just got the following idea. It's simple and while it doesn't allow to fully automate the setup of a secure channel between Web Browser app and the Native app, it may significantly improve the user experience.
We can use Time-based One-Time Password algorithm (TOTP). In a way, it's similar to how we pair a Bluetooth keyboard to a computer or a phone.
The Web Browser app (where the user is already authenticated) could display a time-based code to the user, and the Native app should ask the user to enter that code as a confirmation. It would then use the code to authenticate against the Web API. That should be enough to establish a back-end channel between the two. The life time of the channel should be limited to that of the session within the Web Browser app. This approach might even eliminate the need for a custom protocol communication in the first place.
Still open to other ideas.

You could try driving the synchronization the other way:
Once the user is authenticated into the web app, launch the native app from the web app via the custom URL scheme.
If the native app is not authenticated, connect securely to the backend over HTTPS, create a record for the native app, retrieve a one time token associated with that record and then launch the web app in the user's browser with the token as a URL parameter.
Since the user is authenticated in the browser, when the server sees the token it can bind the native app's record with the user account.
Have the native app poll (or use some other realtime channel like push notifications or a TCP connection) the server to see if the token has been bound to a user account: once that happens you can pass a persistent auth token that the native app can store.

Did you think about using LDAP or Active Directory?
Also OAuth2 could be combined, here are a related question:
- Oauth service for LDAP authentication
- Oauth 2 token for Active Directory accounts
SSO should be easier then too, furthermore access-rights could be managed centralized.
Concerning general security considerations you could work with two servers and redirect form the one for the web-application to the other one after successful access check. That 2nd server can be protected so far that a redirect is required from the 1st server and an access check could be made independent again but without need to login another time, might be important to mention here the proposed usage of Oracle Access Manager in one linked answer for perimeter authentication.
This scenario with two servers could be also hidden by using a proxy-server in the frontend and making the redirects hidden, like that data-transfer between servers would be easier and secure too.
The important point about my proposition is that access to the 2nd server is just not granted if anything is wrong and the data are still protected.
I read here some comments concerning 2FA and some other ideas like tokens, surely those things increase security and it would be good to implement them.
If you like the general idea, I'm willing to spend still some time on the details. Some questions might be helpful for me ;-)
EDIT:
Technically the design in detail might depend on the used external authentication provider like Oracle Access Manager or something else. So if the solution in general sounds reasonable for you it would be useful to elaborate some parameters for the choice of a external authentication provider, i.e. price, open-source, features, etc.
Nevertheless the general procedure then is that the provider issues a token and this token serves for authentication. The token is for unique one-time usage, the second link I posted above has some answers that explain token-usage very well related to security and OAuth.
EDIT2
The Difference between an own OAuth2 / OIDC server and a LDAP/AD server is that you need to program everything by yourself and can't use ready solutions. Nevertheless you're independent and if everything is programmed well perhaps even a bit more secure as your solution is not public available and therefore harder to hack - potential vulnerabilities just can't be known by others. Also you're more independent, never have to wait for updates and are free to change whatever you want at any time. Considering that several software-servers are involved and perhaps even hardware-servers the own solution might be limited scale-able, but that can't be know from outside and depends on your company / team. Your code base probably is slimmer than full-blown solutions as you've only to consider your own solution and requirements.
The weak point in your solution might be that you have to program interfaces to several things that exist ready for business-frameworks. Also it might be hard to consider every single point in a small team, large companies could have more overview and capacity to tackle every potential issue.

Related

Xamarin Authenticate and Authorize Users with my Web Api

I've been searching for a solution that makes sense for the past few days, so forgive me if I overlooked something or am ignorant to the correct path.
I have an existing Website built with asp.net framework MVC where users register for Individual Accounts and are stored in a MSSQL Database. I'm creating a Xamarin.Forms app where we want users to login with their website credentials.
I've been looking at Microsoft docs to try and accomplish this. In the past I created an Apache Cordova app (2014) that communicated in a similar fashion successfully (potentially in an insecure way) that called the /Token endpoint and Authenticated the user with 'grant_password' flow and returned the user data to the app.
So I landed on this documentation: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
However, from what I can gather it basically says this should be avoided moving forward and a MSAL approach should be used if possible.
After reading through hours and hours of documentation trying to make sense of it all, I can't seem to grasp what my options are. It seems to me that in any MSAL flow, users will have to login with Microsoft accounts or other social accounts (facebook, google).
Am I missing something?
Am I going to have to go against Microsoft's advice and end up storing the client_id and client_secret within the Xamarin app source code? Which from everything I've read is a big security concern, especially with Android apps.
References: 1. Restrict API requests to only my own mobile app 2. How to secure an API REST for mobile app? (if sniffing requests gives you the "key")
Any help or direction would be really appreciated. Thank you
Your focus should be on requirements + understanding preferred designs rather than jumping to a technology.
DIRECTION
Standard modern systems look like this:
Mobile apps use OpenID Connect to sign users in
Authorization Server issues access tokens to the mobile app
APIs authorize requests via JWTs containing scopes and claims
Aim to make iterative steps towards this type of architecture.
PATTERNS
Plug in an Authorization Server, which uses your existing database as a credential store
Mobile app uses AppAuth Libraries to sign users in and receives access tokens
Back end can handle JWTs without data security risks
DIFFICULT AREAS
Your existing back end may have no support for mobile clients, and be too web focused - eg requiring cookies to access data, so may need to be split in be into 2 entry points.
Choosing an Authorization Server (while you are learning) is difficult, because you may not know what you want yet.
The mobile app will spin up the system browser and present a login page from the Authorization Server, so the login UX could be unexpected.
STEP 1
Ensure that you can authenticate from the mobile app, then make API calls with JWTs and ensure that requests for data are properly authorized. This could use ropc and involve a temporary API. But the deliverable should be that your back end now supports calls from mobile apps.
STEP 2
Integrate AppAuth into the mobile app, which is tricky but there are resources online such as Curity Mobile Guides. Update the mobile app to use the Code Flow and integrate an Authorization Server, then deal with connecting to credential stores.
SUMMARY
This stuff is hard and reflects the cost of modernising architectures. It requires people agreement as well as the technical stuff. Happy to answer follow up questions if it helps.

Userless Automated server to server Oauth2 2 legged authentication to Gmail

I've found plenty of information on implementing Oauth2 using a user authorization step, but I'm trying to run a container that automatically scrapes a gmail inbox for attachments transforms them, and exports to prometheus, and I'm having trouble figuring out how to implement this library: https://pkg.go.dev/golang.org/x/oauth2/clientcredentials#Config or any other for that matter to retrieve a token without involving a manual user step.
Will doing this in Go require writing direct API calls since I can't find an existing library to handle this scenario? Would it make more sense to create a Google App password and use generic user/pass SMTP authentication?
First off i understand what you are trying to do.
You have a backend system running in a container which will access a single gmail account and process the emails.
Now you need to understand the limitations of the API you are working with.
There are two types of authorization used to access private user data
service account - server to server interaction only works with workspace domains. No authorization popup required.
Oauth2 - authorize normal user gmail accounts, requires user interaction to authorize the consent screen
If you do not have a workspace account and this is a normal gmail user then you have no choice you must use Oauth2, which will require that a user authorize the application at least once.
Using Oauth2 you can request offline access and receive a refresh token which you can use to request new access tokens when ever you wish. The catch is that your application will need to be in production and verified, because your refresh token will only work for seven days and then it will expire. To fix this and get a refresh token that does not expire means that your application must in production and verified. This means you need to go though Googles verification process with a restricted gmail scope which requires third party security check and costs between 15k - 75k depending upon your application.
I understand that this is a single user system but that does not mean that you still need to go though verification. When google added the need for application verification they did not take into account single user systems like yours.
Option
Have you considered going directly though the SMPT server instead of using the Gmail api? If you use an apps password you should bypass everything by loging in using the login and the apps password.

Should I protect UI in web application?

We have a web application with Rich Client Architecture.
We use React for our client side and Java/Spring for our back-end.
Now the question is should login page be a part of our react program or not?
As I know, if we do so, the downsides are:
The UI is not protected and everyone, even those without any access, can download the whole UI app.
Everyone, even without access must download the whole UI application before logging in.
And the upsides are:
The page need not to be refreshed when someone logeed in.
Front-end and back-end parts can be totally separated without any shared sessions.
In most known apps such as gmail, slack, etc. the rich client app (angular, react, etc.) is just after logging in and I just don't know any application with the first approach.
Frontend is generally not protected. There are potential ways to make it harder to brake code, but it will be always possible.
Because of 1 -> you should not keep any sensitive data in frontend.
As an secured way of transfering data from Spring backend to React(or any other like Angular,VueJS etc) you should probably use JWT or OAuth2.
You can decode your JWT on frontend (but only backend can verify if it is valid token so don't worry) to get encoded scopes,roles etc to use them e.g. to show admin only options.
To answer your question - login page definitely can be part of React app, as it will send login credentials and get back JWT from backend
When user is logged in - you will attach JWT in headers with every request, so your Spring Security can check it and authorize request.

Can Oauth2 replace session (or other similar means) to keep user login information at server side?

I'm a little new to this and please bear with me if I ask dumb questions.
As what I know, session is something saved at server (either in file or in database), and client access it via sessionid saved in cookie. To keep user login information, we can simply put a 'logged_in' column and an 'expired' column in session file or session table.
As far as I know, Oauth2.0 is designed for third party client to access the server. The whole process is controlled by an access_token, which is quite similar to sessionid (at least from my knowledge).
So, here's my question, is it possible to use Oauth2.0 to completely replace session? I.e., even people are using the website designed by me (NOT third party website) to access my own server? So that I have a unified authorization framework for user accesses both from my own website and any thrid party website.
Is there any pros&cons of using session & oauth 2.0?
Lastly, how about mobile app? I know for third party mobile app, they normally use oauth to access the server (many websites provides oauth api). How about if I am going to write my own app for my own server (NOT third party)? Does Oauth 2.0 apply here too?
To summarize, my question is actually is, is Oauth 2.0 universal that can be used in all kinds of user authorization control situations from all kinds of devices?
Thank you very much.
Though both are short-living entities, session IDs and OAuth tokens are fundamentally different and used for distinct scenarios. A session is used to identify a user of a web application, thus related to the end user. An OAuth token is used to grant access to a third-party service to access a limited set of protected user resources (e.g. read user contact information or send a mail from the user account). Though the token refers to the granter (i.e. end user authorized the grant), the token related more to the third-party application.
To give you an analogous example: imagine that you have a safe at your bank (i.e. your protected resource). The session is your id for the bank: give it to someone else and he will be you, he can get everything from your safe. On the other hand, a token is a limited authorization to someone else to your safe: e.g. your approval that he can get 10$ from your safe while a security guard is watching.
As a summary, sessions and tokens are not interchangable.

How do I implement OAuth 1.0 in a Windows Phone 7 app without asking the user for their password?

I am building a WP7 Twitter client. The normal OAuth 1.0 flow involves obtaining a request token by navigating a web browser to https://api.twitter.com/1/oauth/authenticate with my app's consumer key; this page will show a login prompt and ask the user to authorize my app to perform actions on their behalf. Upon completion, this page will redirect to a callback URL supplied by my app, with the request token supplied as a parameter.
For web apps this makes sense. I don't understand how this is supposed to work for a standalone mobile/desktop app, though. The Twitter API documentation seems to imply that this should be a feasible option. They do offer an alternative xAuth mechanism that allows an app to gather username/password itself and then supply that directly to obtain an access token. The API documentation points out that this is an inferior option (as it requires the user to trust the app, not just Twitter, with their password), but I don't see how I have any reasonable alternative?
(there is also a PIN-based option, but that's a pretty burdensome solution for the user)
I just want to make sure I'm not missing anything obvious.
"For web apps this makes sense. I don't understand how this is
supposed to work for a standalone mobile/desktop app, though."
Just embed a web browser control in your app, and navigate to the twitter authentication page. Then detect the redirection to the callback url (using the Navigating event) and retrieve the parameter. Many twitter apps do that, it's basically the same as asking the user for the login and password, except that instead of your own controls you're displaying twitter's page.
Nope, you're correct. The option for a mobile/desktop application is either a pin-based option or to use xAuth. Once you have an xAuth application has an access token it is indistinguishable from OAuth (it only changes the authorisation workflow). One thing it does change, and this is very specific to Twitter, is that if you do use xAuth then your application will not be allowed to read or write Direct Messages. See Twitter's The Application Permission Model page for more information.

Resources