I'm trying to build the foundation for my iPhone app and server. I have users who will sign up and sign in from the iPhone app. In a normal website login, the http server will provide cookies to allow the user's subsequent requests to remain authenticated. How should I handle this on the iPhone? Should I just send the user/password every single time I have a NSURLConnection GET or POST? That seems excessive. Or do I use the ASIHTTPRequest framework to use cookies. Can anyone point me in the right direction for a proper implementation?
Thanks!
Sending username and password in every request is not great.
You can use anything you want to send cookies. It's just another HTTP header. But that begs the question of what is in the cookie. It depends on what your client/server architecture is. Web apps use session keys because traditionally web clients haven't held any state so the app server had to. Native clients can have all sorts of state and so generally don't need the server to provide that.
But you need authentication. That's what things like OAuth and OAuth 2 are for. They allow you to authenticate once and then use tokens that can be invalidated server-side. Kind of like very long lived sessions without data.
They are a bit complicated but there are open source libraries for both the server and client pieces or you can roll your own. Most of the complication is on getting the original token which you can short-circuit if you own the client and server. OAuth can get pretty complicated because all requests are signed with a secret token. OAuth 2 can be as simple as a shared secret (thus requiring SSL) in a cookie.
Related
Yohoho! I am building an application that leverages OAuth to pull user data from provider APIs, and am wondering about the RFC compliance of the flow I have chosen.
Currently, the user signs into the authorization server which sends an auth code to my frontend client. The frontend then passes the auth code to my backend, which exchanges it for an auth token and then makes calls to the provider to pull data.
In this best practices document, it states:
Note: although PKCE so far was recommended as a mechanism to protect
native apps, this advice applies to all kinds of OAuth clients,
including web applications.
To my understanding, PKCE is designed to ensure the token is granted to the same entity that requested the auth code, in order to prevent attackers from using stolen auth codes to execute unwarranted requests.
Now, it makes sense to me why this is important even if the backend keeps the client secret unexposed, since the attacker can make requests to the backend with the intercepted auth code to receive the token. However in my flow, since I am not creating an authentication scheme and rather trying to authorize premeditated requests, the token stays with the backend.
So why is PKCE recommended here? It seems to me the most a stolen auth code can do is initiate an API request from the backend, with no token or data being returned to the attacker. And assuming a PKCE implementation is the way to go, how exactly would it work? The frontend requesting the auth code and the backend trading it for a token aren't exactly the same, so would it be as simple as passing the code_verifier to the backend to make the call?
Some clarification would be greatly appreciated.
PKCE ensures that the party who started the login is also completing it, and there are two main variations that I'll summarise below in terms of Single Page Apps (SPA).
PUBLIC CLIENTS
Consider a Single Page App that runs a code flow implemented only in Javascript. This would store a code verifier in session storage during the OpenID Connect redirect. Upon return to the app after login, this would be sent, along with the authorization code and state to the Authorization Server.
This would return tokens to the browser. If there was a Cross Site Scripting vulnerability, the flow could be abused. In particular the malicious code could spin up a hidden iframe and use prompt=none to get tokens silently.
CONFIDENTIAL CLIENTS
Therefore the current best practice for Single Page Apps is to use a Backend for Frontend (BFF), and never return tokens to the browser. In this model it is more natural for the BFF to operate like a traditional OpenID Connect website, where both the state and code_verifier are stored in a login cookie that lasts for the duration of the sign-in process.
If there was a Cross Site Scripting vulnerability, then session riding is possible by the malicious code, to send the authorization code to the BFF and complete a login. However, this would just result in writing secure cookies that the browser cannot access. Similarly, the hidden iframe hack would also only rewrite cookies.
The code_verifier could alternatively be stored in session storage and sent from the browser to the BFF, but it would be easy enough for malicious code to grab it and also send it to the server. This does not really change the risks, and the key point is that no tokens should be returned to the browser. It is OK to use secondary security values in the browser, as long as you can justify them, eg for security reviewers. Generally though it is easier to explain if secure values are in secure cookies and less visible to Javascript.
FURTHER INFO
Best practices often vary depending on the customer use case, and at Curity we provide resources for customers (and general readers) to explain secure design patterns. These are based on security standards and we translate them to customer use cases. You may
find our recent SPA Security Whitepaper useful.
I've got an OAuth2-driven authorization system for the applications in my ecosystem using the Auth Code flow. At the moment, it is working extremely well following what I feel are best practices. My current flow can be summed up as this:
User clicks a Login button in application frontend.
Backend for application redirects user to Auth Server login page with redirect URI, client ID, etc, in params.
User logs in, Auth Server redirects to Backend /authcode endpoint with Authorization Code.
Backend authenticates with Authorization Code, receives Access (JWT) & Refresh tokens. It stores Refresh token in its own database, and returns Access token as an HTTP-Only cookie.
When Access token expires, Backend sends Refresh token to Auth Server to refresh.
The problem with this approach is it is heavily dependent on a single-backend/monolith/etc architecture. When the access token expires, the backend app in question needs to be able to get the refresh token and then do the refresh against the Auth Server.
My goals for the future state of this architecture are driven by two main concerns:
Allowing backends to be split into multiple micro-services that are all capable of authenticating the same JWT.
Supporting SSO. Currently, even though all users are managed through the same Auth Server and use the same credentials, they need to enter those credentials separately for each app they log into.
My initial thought was to move the refresh handling to the client-side part of the architecture. Since all the apps are owned by me, I could setup a new flow where a user would login directly with the Auth Server, and then the Access (JWT) and Refresh tokens are set as HTTP Only cookies. This is further supported by the fact that all of my apps are hosted via a single domain name (with different root URI paths for different apps). The new token structure would determine which apps a given user has access to.
My concern there is how to secure the Refresh Token client-side. Most likely I would need to use the Path attribute and depend on the fact that all my apps are on the same hostname, which as I said they are and that will not be changing.
I guess the point of this post is I'm looking for guidance on best practices for handling this kind of scenario.
A few thoughts based on design patterns we recommend at Curity:
BACKENDS AND JWTs
Related APIs should be able to forward JWT access tokens to each other, as detailed in the scopes article. Validating the JWT in each API results in a recommended zero trust setup.
BACK END FOR FRONT END
We recommend a particular way of doing this, focused on separation of web and API concerns - see this code example on the token handler pattern.
Token refresh is handled via HTTP Only cookies and client side retries. This provides a stateless solution that is easy to manage, and where the web back end is static content only, eg a content delivery network. It requires a couple utility API components to be deployed though.
An alternative option, as you say, is to write code within your back end to store tokens, so that cookies only contain a Session ID.
COOKIES AND MULTIPLE WEB APPS
In our resources we use reverse proxies / API gateways as the entry point to APIs, rather than a web back end. Common plumbing such as translating cookies to tokens can then be managed via gateway plugins - as covered in this tutorial.
However, when you have multiple web apps you need to keep cookies isolated during API requests. Each app therefore needs its own API routes. This is awkward but is a consequence of needing to use secure cookies for best browser security. It is best managed in the gateway, and separate domains or subdomains is usually cleanest:
https://api.brand1.com
https://api.brand2.com
Each web team is then responsible for their own API routes and the cookie / CORS / CSRF stuff, rather than the API developers.
SSO
This should be determined solely by the Identity Provider session cookie, which will remain valid as you navigate across apps. If you are presenting a login button when the app does not have a secure cookie yet, then it will not feel like SSO though. One technique for making SSO look seamless is for each app to automatically redirect when it does not have application cookies yet, rather than presenting a login button.
SUMMARY
A long answer, but the best solutions require separation of concerns that is not always obvious. Done well, the end result should be simple code in apps, correct security and an architecture that can be scaled.
After watching an obscene amount of tutorials on OAuth2, there is one best practice that everyone repeatedly states - if you have a React app (or Angular, or Ember) - you must use Implicit flow with it.
I understand that storing client credentials in publicly visible javascript would not work. However, my scenario is a bit different:
I'm only using Oauth2 for single sign on and token generation for microservices. I chose it instead of simply generating tokens, since well-supported third party libraries are built around the Oauth2 idea.
My idea is to have a React app, and a ASP.NET MVC app which serves the javascript and acts as a proxy for API requests. The user authenticates for the server-side app (by using Oauth2 authorization code flow).
Then if I need to retrieve data from an API, I call my ASP.NET MVC app from React (by sending a simple cookie). The MVC app holds the token without ever exposing it to the user's browser.
Obviously, when called, my MVC app then redirects the request to the necessary API, providing the bearer token.
To better understand why this is what I came up with, here are some requirements I've received that might be unusual:
I really don't want the access token to be shared - even if it's relatively short lived.
I also want to be able to limit each user account to 3 concurrent user sessions. Easy to do using cookies and server-side sessions.
I can't wrap my head around why this idea would be that bad. Is there any technical problem that might prevent this from working? Or maybe a security risk?
The authorization code flow returns an authorization code (like it says on the tin) that can then be exchanged for an ID token and access token. This requires client authentication using a client id and secret to retrieve the tokens from the back end and has the benefit of not exposing tokens to the User Agent.
This flow allows for long lived access (through the use of refresh tokens).
Clients using this flow must be able to maintain a secret.
Accordingly to your description, you have service-to-service authorization flow, and as your service are not exposing client secret key it is totally OK to use the Code flow. Moreover, you should use it to allow long lived tokens.
OK. So i need some guidance as I am a total iOS authentication noob.
I have a simple app. Users can login to the app, and send messages to friends. There is a web server and a MySql Database that holds the users and login information.
Question: How do I authenticate a user when he logs in safely and securely?
I have spent the last several hours hurting my brain on the following authentication stuff i found from google:
OAuth 1.0 - is said to be good. But it is a protocol and not a library. Do i have to implement this from scratch? Is this even needed in my case for authentication?
OAuth 2.0 - it seems that some sites are using this. I have the same questions for this as version 1.0. I also saw this this message from the library's lead creator literally saying f*** version 2.0 because it was bad for security. But yet so many still use it. Is it dangerous?
The creator of 2.0 has now gone on to make a completely other library because of how bad 2.0 was and because of how unscalable 1.0 was. His library is called OZ. Should I be using this for my server?
I see AlamoFire/ AFNetworking have basic authentication shown in their documentation. Should i just screw the oAuth stuff and just use theirs?
Being new to the authentication thing, all this is very confusing to me. Can anyone knowledgeable in this provide some guidance?
I am currently in the process of creating a cross-platform application and have spent quite some time researching this!
My approach to the project is using a ASP.NET Web API using OWIN middleware.
This uses bearer tokens to authenticate the user.
Using Microsoft.Identity you can limit endpoints down to roles or even individual users (Autherization)
Currently I create a user on the REST API, They log-in at the /token endpoint and then receive a token. This token is then saved to the Apple key chain and can be used to authenticate the user for further requests to the API.
As long as you use SSL this is a secure method and is used widely in many applications.
This approach uses OAuth2 also, so you'll be albe to easily integrate Facebook/Google/etc integration.
Here is a link to the Microsoft Documentation for some further reading on how I did it:
http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
Currently this is working perfectly for me for an angular front-end but would work exactly the same in iOS except you may want to save the token to the KeyChain Storage.
We mostly use OAuth 2 creating custom system on iOS to handle the authentication.
Nothing is ever bullet-proof but the 2 token system decreases the chance for stealing credential quite nicely.
The AlamoFire, AFNetworking or any other libraries you amy find have nothing to do with this though. What type of credentials you use depends on your choice or rather the choice of the API. You may use these tools to ease your communication with the API though.
So what the idea behind this is you will try to send your user name and password only once when logging in and then you will receive the two tokens which are further used to communicate. This will decrease a chance for someone to intercept the request with the user name and password which are the ultimate key to get the access to the user data.
Next is "refresh token" which is used to receive a new "access token". This call should be made every few hours or so (controlled by the API). If someone was to steal this token he would be able to use it to get further access for an infinite duration or until the owner chooses to invalidate the refresh tokens (this is what happens when you click "log out from all devices"). So this is still quite bad if someone gets it.
Then there is the "access token" which is used for each and every further request to the server. These tokens have a limited time till they are invalidated so if someone was to intercept it somehow he would have the access to the data for the duration of the token.
So assuming this is the procedure that is done on the backend this is what you need to do:
If you have the access token and is valid simply use the service
If you receive the error that the access token is invalid you need to refresh the access token using your refresh token
If refresh token reports an error you need to navigate back to the login screen
If the app has no refresh token then simply go to the login screen
There are some other things that are nice to cover such as if the request reports an invalid token you should pend the request, refresh the token and then repeat the call to the pending request. A system around this may be quite large.
This is pretty much it about the tokens and authentication but there are other parts of the communication which increase the security such as using a https secure connection. When talking about security you must take a look into every part of the communication.
I have a web app split into 2 parts.
A javascript front-end. (myfrontend.com)
API backend (node.js). (mybackend.com)
These 2 parts are hosted on different domains, I need it to be this way because eventually I will build out more front-ends for the same backend (i.e., mobile web apps, etc.)
The way I'm authenticating right now:
A user logs in from myfrontend.com , the credentials are sent (ajax) to mybackend.com where they are checked against the DB. If they don't check out nothing happens and mybackend.com responds with an error code.
If they do check out, I use express.js' cookie-sessions and mybackend.com responds with a cookie (for the mybackend.com domain) . The server links the user-id retrieved from the DB to the session.
From then on, all requests to mybackend.com include the cookie, the backend uses the cookie to find the session, and uses the user-id info in the session to respond correctly.
I had a bunch of CORS issues with this initially, but after setting all the right headers (like withCredentials, etc.) everything is working great, in every browser.
I thought this was a very elegant solution, because all user info is quarantined tightly on the backend, the front-end never receives any user-data, only a short-lived cookie.
So I have 2 questions:
Is this the right way to do this kind of thing? How is OAuth implemented differently from this, and are there advantages?
If I turn off third-party cookies in chrome, this stops working. However turning off third-party cookies in safari still allows this to work fine. What's the deal? Why is getting a cookie for "mybackend.com" when you ajax to "mybackend.com" considered a third party cookie? Would it be ok if I used an iframe or something? Should I worry about this?
Yes, this is a good pattern to use. I used the same approach in http://hackhall.com (https://github.com/azat-co/hackhall). OAuth is more for a three way authentications: consumer, service provider and your app.
OAuth 1.0 requires "oauth dance" to get the the access token which is time sensitive. OAuth 2.0 is easier because after consumers get tokens the first time they can be exchanged for permanent bearers that acts as a password.
OAuth Echo is for delegated calls/requests.
Something to do with the strictness of browsers and/or cookie headers?