I am building an express server that will be used with an iOS native mobile client.Users of the app will be able to form "parties" with other users, and users within the same party will be able to communicate to each other via socket.io.
I want to enable sessions so that 1) I can have persistent login on my frontend and 2) store user.party_id inside a session, so that for a particular user I always have access to his party. If the user leaves a party, then req.session.party_id will be set to null.
Is is possible to use express-session with a native mobile client? I would assume so, and that all the client has to do is set a cookie header on each request. The server then reads the cookie id, and has access to the user session. Are there any drawbacks to using a session with native mobile clients?
Are there any drawbacks to this approach? Someone suggested that instead I set a JWT as an Authorization header, and on each request, use that header to lookup the user and party_id. This approach seems to be a reinvention of a session.
Check out Swift: How to remember cookies for further http requests for info on how to save a cookie/session cookie.
As to JWT vs. session cookies, they do serve similar purposes. JWT is more widely used today as it enables you to have multiple servers that handle API requests (i.e. horizontal scaling or serverless architectures) and are more fault tolerant (i.e. still work even if the server restarts). Depending on your needs, it might be worth looking at JWTs.
Related
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.
I have a scenario in which a mobile (native) app is requiring data from a long running task. The task is a continuesly running on the users behalf, and we have decided to move it to a backend service. To execute the task, the backend service must regularly fetch data from an API that is OAuth2 protected.
Our dilemma is that we are not sure how to provide the backend service with a set of access tokens to access the data API. Our mobile app uses the OAuth2 Authorization Grant flow with PKCS to get its own access token, refresh token and id-token (we use OpenID Connect). But how do we provide our backend service with a set of tokens? As the backend is continuesly running (also in absence of the mobile native app) we would like to provide it with its own set of access/refresh tokens.
There seem to be several solutions:
Proxy all mobile app communication to external APIs via the backend, make the client a private client, use the authorization code flow, and setup custom login sessions between the native app and our backend. To me this means more running backend infrastructure, and implementing session management including session refresh, etc. which is like re-implementing the OpenId flows on my own servers...
Using OpenID hybrid flow, providing both an access token as well as an authorization code to be shared with the backend. However, this seems to be directed at (in-browser) web-apps, not so much native mobile apps as it based on the implicit flow and as such less secure.
Doing the authorization code flow twice on the mobile app (optionally second time with prompt=none to suppress user interaction), keeping one code for the app, forwarding the second to the backend. Then both backend and app can exchange their own codes for access tokens. This feels a bit like a hack as the backend should be a private client, not a public client. It is the approach that Google seems to advertise though in CrossClientAuth
Performing impersonation by sending the id-token to the backend which then exchanges that id-token for its own set of access/refresh tokens. Microsoft does this through the jwt-bearer grant in its "on-behalf-of" scenarios. Moreover, the token-exchange RFC seems to cover the same use-case. However, in this scenario the id-token is indirectly used as access credential, not just as a bag of claims about the user identity, which is odd in my view as access should be controlled through access tokens, is it not? Moreover, not all services should be allowed to impersonate, so I suppose this comes with additional configuration complexity.
To me it feels that I'm overlooking something, this must be a problem others have too and must have been solved before... What would be best practice in my situation?
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?
Currently building an app that will offer up some data based on location. This isn't considered very sensitive information, but I've been wondering what is the best possible way to protect the web service calls credentials in iOS, service is secured by OAuth. I know I could have a web-view and present the data that way, but really don't want to go that route.
Essentially I'm looking for the best possible way to protect the credentials of the web services that will be called from iOS which could be reverse engineered. Thinking of companies like Yelp, Foursquare, ect. How do you suppose they are providing data without requiring a login on iOS and keeping their web services secure?
OAuth 2.0 relies on SSL for encryption between the client and server.
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.