I am tasked with developing the authentication/authorization infrastructure for the following application setup:
Multiple APIs
Web application
Mobile (Native) apps
Support for social login as well as user logins created through a registration process
I've been happily implementing the following:
Identity Server
ASP.Net Core Identity
OIDC dynamic registration for the mobile apps
Authorization Code flow with PKCE for the mobile apps
Hybrid Flow for the Web application
Passing bearer tokens to the APIs
All was good until the client decided that they really, really dislike the mobile experience of opening up a browser to authenticate. They much prefer the idea of showing the username/password inputs in the app.
I know that Auth Code + PKCE is currently the best practice and that any other solution sacrifices some security. My understanding is that using embedded "web views" is frowned upon or are even banned in certain situations. So my question is:
What alternatives to Auth Code + PKCE are there that are still acceptable from a security standpoint yet would maximize the mobile user experience (and minimize redirects)?
I understand the concern and at my last company there were big issues with mobile login usability:
Look and feel was important - and logins may be the very first experience people have with your app
Password autofill never worked on webviews - high profile users had to type their password on small mobile keyboards on every login - they forgot the password on 50% of logins leading to huge frustration
The solution everyone liked was to use AppAuth libraries with chrome custom tabs (Android) + aswebauthentication session iOS)
The tech is not perfect and is tricky to implement - but it is the best usability option I think. See my write up and maybe run it by your stakeholders: https://authguidance.com/2019/09/13/android-code-sample-overview/
Related
i'm developing a simple news App where users can see latest news without login, i don't know how to make it secure, i have read that JWT with OAuth2 should be used but from my understanding the user have to login into a provider to get the token but i want users to be able to read data without login.
my concern right now is how to prevent other people from using my API in their apps, i'm concerned also about DoS attacks.
THE CHALLENGE
i'm developing a simple news App where users can see latest news without login, i don't know how to make it secure
Well you bought yourself a really huge challenge, because even if you required your users to login, it would continue to be a huge challenge, because the web as we know was designed in their earlier days with the naive assumption that only good faith people would use it, thus it becomes a very hard task to secure something that was not designed to be secure in first place.
Securing and locking an API server to a specific app requires that some kind of secret needs to be used in every request in order to authenticate What is doing the request, but once you release a web app or mobile app into the public any secret on it is now in the public domain, therefore not a secret anymore, as it's best you can use it as a weak identifier.
Web App
A web app runs in the browser, thus all an attacker needs to do is to inspect the page source and extract the secret, and then use it in automated scripts or in manual requests from curl or tools like Postman.
Mobile App
Some developers think that because a mobile app is released as a binary that they can just put the secret there and no one will find it... Well I have to say that in the past I was one of them, but then I came to learn that a lot of open source tools exist to make this task trivial that even a script kid can do it. My preferred tool to do this is the MobSF, and you can see an example of using it in this article I wrote How to Extract an API Key from a Mobile App with Static Binary Analysis:
The range of open source tools available for reverse engineering is huge, and we really can't scratch the surface of this topic in this article, but instead we will focus in using the Mobile Security Framework(MobSF) to demonstrate how to reverse engineer the APK of our mobile app. MobSF is a collection of open source tools that present their results in an attractive dashboard, but the same tools used under the hood within MobSF and elsewhere can be used individually to achieve the same results.
MobSF - Mobile Security Framework:
Mobile Security Framework is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing framework capable of performing static analysis, dynamic analysis, malware analysis and web API testing.
The take away is that once an app is released any sensitive information shipped within it must be considered compromised.
JWT and OAUTH2
i have read that JWT with OAuth2 should be used but from my understanding the user have to login into a provider to get the token
Yes, the user would be required to login to get the OAuth token, but any type of token that comes from a user login successfully just identifies Who is in the request, not What is doing the request, and in my experience this is a very common misconception among developers, no matter if they are a junior or a senior developer.
The Difference Between WHO and WHAT is Accessing the API Server
I wrote a series of articles about Mobile API security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between Who and What is making the reques to your API server:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
You may be surprised that sometimes even your legit users may be the ones attacking your API server in order to try to get benefits from your service that otherwise they wouldn't have access.
SECURING AND LOCKING THE API SERVER TO AN APP
but i want users to be able to read data without login.
my concern right now is how to prevent other people from using my API in their apps
To achieve this requirements in your app you need to find ways to secure and lock your API server to only serve requests from genuine instances of your web and mobile apps.
I have to say that for mobile apps this can be achieved with a very high degree of confidence when a Mobile App Attestation concept is employed, but for web apps we just can do it in a best effort basis, by using Artificial Intelligence solutions.
To understand how you can do it for a web app please read this answer I gave to the question Secure api data from calls out of the app, specifically the section entitled Defending The API Server.
For a mobile app you should read this answer I gave to the question How to secure an API REST for mobile app?, more specifically at the section Securing the API Server and the section A Possible Better Solution.
If you have read both the answers I linked above you may understand now better why I said initially that was a huge challenge.
DoS ATTACKS
u'm concerned also about DoS attacks.
This is not normally addressed at the application level, instead it his best handled at the infrastructure level, like in the Firewall, where rules can be applied to identify and drop DoS packets, but if they are to strict they may also block legit users, while if they are too relaxed they let pass DoS packets. To have more effective DoS attacks protections you need to resort to specialized software, and even this ones may need manual intervention during an huge scale DoS attack.
So my advice here is that you start by adding to the Firewall some rules to drop DoS packets, and/or if you are using a cloud provider you may want to see what level of DoS protection they can offer in your account. I know for example that some CDN providers do offer DoS protection for free until some extent, thus may worth you consider to have all your traffic routed through a CDN, that also brings the other traditional benefits of a CDN, aka serving assets from a closest location to your customers.
DO YOU WANT TO GO THE EXTRA MILE?
In any response to a security question I don't resist to reference the excellent work from the OWASP foundation.
For Web Apps
OWASP Web Top 10 Risks
The OWASP Top 10 is a powerful awareness document for web application security. It represents a broad consensus about the most critical security risks to web applications. Project members include a variety of security experts from around the world who have shared their expertise to produce this list.
The Web Security Testing Guide:
The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.
For Mobile Apps
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
Let's imagine the following:
I've developed a mobile app using Xamarin (iOS/Android compatible)
I want it to support OAuth2 + OpenID connect's authorization code flow with PKCE, so that the user's credentials are never stored on the device, but rather an access token is. The token grants access to an API used to make the whole mobile app function, meaning the mobile app is simply a front-end interface/UI.
Is my mobile app considered the "client application", or the "Resource owner"?
The third step makes it so hard for me to grasp this. If it's considered client application, how will following through the whole code flow, protect us from anything, as most of the things will be visible (Mobile apps are public clients, there is no back-channel)
If it's considered resource owner, then does that mean I'd have to whip out an entire dedicated back-end, separate from my API, separate from my Authorization Server, and just specific for the mobile app (it will be the "Client application")?
If someone could shine some light on this, please let me know. The title is not very correct, if it can be edited to better fit this question, I'd be very thankful.
Your mobile app is the client application - with a trust entry configured in the Authorization Server. PKCE works by the mobile app generating a runtime secret used in 2 messages:
The login redirect
An authorization code grant message
See steps 4, 7 and 8 from my article to understand PKCE messages.
Mobile OAuth involves integrating AppAuth libraries which is not easy, though you'll have the best security and usability once complete.
I have a sample Android app and article that you can easily run.
The behaviour on iOS is similar.
I have an OpenID Connect provider built with IdentityServer4 and ASP.NET Identity, running on let's say: login.example.com.
I have a SPA application running on let's say spa.example.com, that already uses my OpenID Connect provider to authenticate users through login.example.com and authorize them to access the SPA.
I have a mobile app (native on both platforms) that is using a custom authentication system at the moment.
I thought it would be nice to get rid of the custom auth system, and instead allow my users to log-in with the same account they use on the SPA, by using my OpenID provider.
So I started by looking on the OpenID connect website and also re-reading the RFC6749, after a few google searches I realized that was a common problem and I found RFC8252 (OAuth2 for Native clients), also Client Dynamic Registration (RFC7591) and PKCE (RFC7636).
I scratched my head about the fact that it was no longer possible to store any kind of "secret" on the client/third-party (the native apps) as it could become compromised.
I disscussed the topic with some co-workers and we came out with the following set-up:
Associate a domain let's say app.example.com to my mobile app by using Apple Universal Links and Android App Links.
Use an AuthenticationCode flow for both clients and enforce them to use PKCE.
Use a redirect_uri on the app associated domain say: https://app.example.com/openid
Make the user always consent to log-in into the application after log-in, because neither iOS or Android would bring back the application by doing an automatic redirect, it has to be the user who manually clicks the universal/app link every time.
I used AppAuth library on both apps and everything is working just fine right now on test, but I'm wondering:
Do you think this is a secure way to prevent that anyone with the right skills could impersonate my apps or by any other means get unauthorized access to my APIs? What is the current best practice on achieving this?
Is there any way to avoid having the user to always "consent" (having them to actually tap the universal/app link).
I also noted that Facebook uses their application as a kind of authorization server itself, so when I tap "sing-in with facebook" on an application I get to a facebook page that asks me if I would like to" launch the application to perform log-in". I would like to know how can I achieve something like this, to allow my users login to the SPA on a phone by using my application if installed, as facebook does with theirs.
I thought it would be nice to get rid of the custom auth system, and instead allow my users to log-in with the same account they use on the SPA, by using my OpenID provider.
This is what OAuth 2.0 and OpenID Connect provides you. The ability to use single user identity among different services. So this is the correct approach .!
it was no longer possible to store any kind of "secret" on the client/third-party (the native apps) as it could become compromised
Correct. From OAuth 2.0 specification perspective, these are called public clients. They are not recommended to have client secrets associated to them. Instead, authorization code, application ID and Redirect URL is used to validate token request in identity provider. This makes authorization code a valuable secret.!
Associate a domain let's say app.example.com to my mobile app by using Apple Universal Links and Android App Links.
Not a mobile expert. But yes, custom URL domains are the way to handle redirect for OAuth and OpenID Connect.
Also usage of PKCE is the correct approach. Hence redirect occur in the browser (user agent) there can be malicious parties which can obtain the authorization code. PKCE avoid this by introducing a secret that will not get exposed to user agent (browser). Secret is only used in token request (direct HTTP communication) thus is secure.
Q1
Using authorization code flow with PKCE is a standard best practice recommended by OAuth specifications. This is valid for OpenID Connect as well (hence it's built on OAuth 2.0)
One thing to note is that, if you believe PKCE secret can be exploited, then it literally means device is compromised. Think about extracting secret from OS memory. that means system is compromised (virus/ keylogger or what ever we call them). In such case end user and your application has more things to be worried about.
Also, I believe this is for a business application. If that's the case your clients will definitely have security best practice guide for their devices. For example installation of virus guards and restrictions of application installation. To prevent attacks mentioned above, we will have to rely on such security establishments. OAuth 2.0 alone is not secure .! Thats's why there are best practice guides(RFC68129) and policies.
Q2
Not clear on this. Consent page is presented from Identity Provider. So it will be a configuration of that system.
Q3
Well, Identity Provider can maintain a SSO session in the browser. Login page is present on that browser. So most of the time, if app uses the same browser, users should be able to use SPA without a login.
The threat here comes from someone actually installing a malicious app on their device that could indeed impersonate your app. PKCE prevents another app from intercepting legitimate sign in requests initiated from your app so the standard approach is about as safe as you can make it. Forcing the user to sign in/consent every time should help a bit to make them take note of what is going on.
From a UX PoV I think it makes a lot of sense to minimize the occasions when the browser-based sign in flow is used. I'd leverage the security features of the platform (e.g. secure enclave on iOS) and keep a refresh token in there once the user has signed in interactively and then they can sign in using their PIN, finger print or face etc.
I have in the past done a hand rolled app that stores a user token on client side $window.sessionStorage.
I have since then realized this is not safe. I am now looking for the most safe, standard way to secure an app that uses a node/express backend api that I will make, and also uses a front end that makes requests to this api such as angular for web or a native mobile app. Plus, whenever I would close the browser, I would have to re-log in because the $window's session storage was wiped out.
From what I've researched thus far, one of the safest ways to date if you're going to handroll it is to store a jwt in an http only secure cookie.
However, I'd kind of like to use a service that already exists, such as oAuth. Couple questions:
1) How safe is oAuth in terms of keeping ownershp of your userbase? What if 3 years from now oAuth just suddenly or slowly dies out? Aren't all my users technically stored on their server? How would I keep my users native to my app?
2) If I'm going to be creating a startup app in the same realm as snapchat, twitter, tumblr, etc... would it be generally recommended to use a service like oAuth to handle my authentication? Of course the future is unknown, but assuming the best, that my app would reach millions of users, would using a service like oAuth still be a smart choice? It seems like once you start using oAuth, there's never any going back to storing your users in your own database a year or two down the road.
Thanks
OAuth is an open standard for authorization.
Maybe you're thinking about Auth0. There are a lot of services that can handle user authorization for you, including Auth0, Stormpath, Apigee, UserApp, AuthRocket or Amazon Cognito. Whichever you choose, make sure that you can get the database from them in case you want to stop using their service. Not everyone explicitly offers an easy way to leave them but if that's important for you then make sure who suits your needs and who doesn't, and base your decision on that.
As for OAuth, see the https://en.wikipedia.org/wiki/OAuth article.
There's a huge list of OAuth providers on Wikipedia but those are services like Twitter, Google or Facebook. In a way you can use one of those services to manage all your logins but as soon as they see you as their competition, you're in trouble. I've heard stories like that.
Some interesting read on the subject:
The dangers of OAuth/Social Login
Signing Me onto Your Accounts through Facebook and Google: a Traffic-Guided Security Study of Commercially Deployed Single-Sign-On Web Services
OpenID Vulnerability report: Data confusion
Social Login Setups – The Good, the Bad and the Ugly
At the moment we are building a web shop as a SPA application. All the SKU information is provided by a Web Api 2 service.
Of course the web shop is publicly available to every visitor, and currently there is only one user who can log in to manage the web shop: the administrator.
For the administrator we built in the basic authentication with the bearer token, as a lot of samples on the internet shows us, but now we need every user to log in before they can see any product. Not really what we have in mind for a web shop ;-)
What we would like to implement is that our Web Api is not available to the world but only for our SPA application. Every blog post or tutorial on authorization seems to assume that there is always a user that needs to log in, in our case there is only one user: the administrator.
The AllowAnonymous attribute makes specific API calls available to the world again, so that's also a dead end.
Basically it comes down to preventing any other apps (web or mobile) to fetch the data from our Web Api.
What would be the best and most secure approach to secure our Web Api without having the anonymous visitors of our web shop to log in?
Solution for now: Altough I'm not 100% happy with this solution, it will work for now. We implemented the OAuth Implicit flow with CORS enabled for specific domain.
You should take a look at the OAuth 2.0 client credentials flow. The client in OAuth speak is the application and not the user using the application. This way you can make sure only your SPA app can access the backend API.
The parts that only should allow access to the administrator, you can decorate with the [Authorize(roles = administrator)] attribute, which prevents any other roles from having access.
I think Json Web Token could help you with this. This article has more information about using Json Web Token for granular authorization of your web api.
OAuth 2.0 is inherently insecure, and solely relies upon SSL. It has no encryption, and most of the latest web api gurus are suggesting that it's dead. This again is relative to what you need the security for. If it's for a social SPA where the data isn't financial or medical, for example, and good enough SSL security is ok, then perhaps OpenID or OAuth2 is suitable.
A much better solution is to implement Identity 2.0 for the Web API authentication flow, and then utilize something like Hawk Protocol for HTTP MAC implementation. Check this out : https://github.com/webapibook/hawknet for an example.
For OAuth2 framework and a extensible solution, check out Thinktecture.IdentityServer3 on GitHub
For a lightweight .net 4.5 Web API Tokenization solution, check out Thinktecture.IdentityServer2 on GitHub.
Hope it helps.