Lets say i have 5 applications and I have a common auth server.
My applications redirect the page to auth server for the first time, gets back a JWT token and then allows the user to use the application further.
Now the user is ready to use the application, but the application's backend has no clue on whether the token is still valid or expired. So Am I supposed to make a validation call to my auth server every time an API in my application is called before processing the request? Is it not adding additional overhead (multiple hops) and impacts the response time of the application?
Is it possible for the application to check the validity of the token by itself without making a network call to the auth server? What are the best practices an application developer should follow while using an auth server for SSO?
Is it possible for the application to check the validity of the token by itself without making a network call to the auth server?
Expiration: Include en exp claim into the token with the expiration date. Any client can decode the token and check the date
Signature: The client can verify the signature of the token to check if it comes from the expected server and trust the contained data. Then you would need to use an assymmetric keypair (e.g RSA)
What are the best practices an application developer should follow while using an auth server for SSO?
This question is opinion-based and is off-topic in StackOverflow. Could you be more specific about your doubts or include a programming issue?
Is SSO an overhead?
No, your application is clear example of why a SSO system is needed:
SSO: 5 apps ->1 user login
Without SSO: 5 apps -> 5 user logins
Related
I'm considering a microservice architecture and I'm struggle with authorization and authentication. I found a lot of resources about oauth2 and openid connect that claim they solve the issue but it is not clear enough for me.
Let's consider we have a following architecture:
In my system I want to add a feature only for a certain group of users defined by role. I want to also know the name of the user, their email and id.
After my research I find the following solution to be a good start:
SPA application displays login form.
User fills in the form and sends POST request to authN&authZ server.
The server replies with access token (being a JWT) that contains name, email, id and role of the user. The response contains a refresh token as well.
SPA application stores the token and attaches it to every request it makes.
Microservice 1 and Microservice 2 check if the token is valid. If so, they check if the role is correct. If so, they take user info and process the request.
How far away from the good solution I am? The login flow looks like Implicit flow with form post described here but with implicit consents and I'm not sure if it's fine.
Moving forward, I find passing user data in JWT (such as name, email) to be not a good solution as it exposes sensitive data. I found resources that say it is recommended to expose only a reference to a user in token (such as ID) and replace such token with a classic access_token in reverser-proxy/api gateway when sending a request to a microservice. Considering such solution I think that following scenario is a good start:
SPA application displays login form.
User fills in the form and sends POST request to authN&authZ server.
The server replies with access token and refresh token. API gateway (in middle) replaces access token with ID token and stores claims from access token within its cache.
SPA application stores the token and attaches it to every request it makes.
Handling a request, API Gateway takes ID Token and based on the user ID generates a new access token. The access token is send to microservice 1 or microservice 2 that validate it as previous.
How do you find such solutions? Is this a secure approach? What should I improve proposed flow?
Thanks in advance!
You are on the right tracks:
ZERO TRUST
This is an emerging trend, where each microservice validates a JWT using a library - see this article. JWT validation is fast and designed to scale.
CONFIDENTIAL TOKENS FOR CLIENTS
Internet clients should not be able to read claims that APIs use. The swapping tokens in a gateway concept is correct, but the usual approach is to issue opaque access tokens here, rather than using ID tokens. At Curity we call this the Phantom Token Approach.
SECURE COOKIES IN THE BROWSER
One area to be careful about is using tokens in the browser. These days SameSite=strict HTTP Only cookies are preferred. This requires a more complex flow though. See the SPA Best Practices for some recommendations on security.
SPAs should use the code flow by the way - aim to avoid the implicit flow, since it can leak tokens in the browser history or web server logs.
SUMMARY
All of the above are general security design patterns to aim for, regardless of your Authorization Server, though of course it is common to get there one step at a time.
Don't use your own login form. As Garry Archer wrote, use the auth code flow with PKCE which is the recomended flow for applications running in a browser.
If you don't want to get an ID token, don't ask for the openid scope in the initial auth request. The type of issued access tokens (JWT or opaque) can often be configured on your OAuth2 server. So I see no need to issue new tokens at your gateway. Having more token issuers opens more ways of attacking your system.
Your backend modules can use the userinfo endpoint, which will give them info about the user and validate the token. This way, if the token was invalidated (e.g. user logged out), the request processing will not proceed. If you validate just a JWT signature, you will not know about the token being invalidated.
If you plan to make requests between your backend modules as part of of a user request processing, you can use the original access token received from your SPA as long as your modules are in a safe environment (e.g. one Kubernates).
I can't help but think I've implemented Open ID slightly incorrectly, but I also cannot find why I've done the implementation the way I have is bad or not.
Scenario:
Website - Used forms authentication before being updated to use OWIN. Forms auth has been stripped out.
Website now supports OpenId to Okta. This is being implemented for a large company of our users to facilitate their logins. This is functional.
The method I use for the site models how Microsoft does logins. On email domain detection, we redirect the user to the login page for their domain. In this case, Okta. We receive the callback, and look up the user in our existing data, and generate a cookie based on our existing data (or create a new user account if they don't have one).
Essentially, just using Okta to confirm they are a valid user, and then we log them in with our user data. We foresee doing this for other companies as well.
Problem:
I have a desktop (WPF) client that requires a login to our website. This talks to API's that already exist using an auth key/token system we built many years ago. Ideally, we do something similar. Use Okta to verify the user is a user of that system, then generate a token that can be used for these API's.
Here is where I'm not sure I've done this appropriately.
The desktop client calls an API endpoint on our site with the email domain the user entered. We verify the user's domain is allowed to use SSO, and if so, we issue back a challenge endpoint for the client to call. This challenge endpoint is then called by the desktop client to launch the users default browser.
This challenge endpoint is an endpoint on OUR website, that essentially triggers the challenge to the IdP. After login, a callback is called on OUR website, to process the auth response. We verify the user's account is valid, and get the refresh token from the response. With the refresh token, and an identifier of the user, this data is then sent back to the desktop client using localhost:randomPort so the client can consume the refresh token and identitifer. (Note that I do encrypt the refresh token and identifier's before returning them to the client)
This refresh token is then POSTed to OUR website, along with their identifier (so we can identify the IdP we should call), then use an OIDC client to verify the refresh token is still valid. If the refresh token is still valid, we generate an app token and return it.
Is there a glaring issue with how this is implemented that I'm not seeing? How can I do this differently?
You seem to be missing the role of an Authorization Server (AS) that you own, to manage connections to other systems and to issue tokens to your apps.
You seem to have some good separation and to be doing quite a few things well - eg you are using your own tokens rather than foreign Okta tokens. The main issue is likely to be growing the system.
PREFERRED BEHAVIOUR
An AS should result in simpler code and a system that is easier to extend:
You can add new authentication methods quickly
This should involve just adding a connection (eg Okta) to your AS
Doing so requires zero code changes in your UIs and APIs
Your UIs just use standard OpenID Connect flows and call AS endpoints, regardless of the authentication method used
Your APIs just verify tokens issued by the AS, then authorize requests, regardless of the authentication method used
Some scripting is needed in the AS, but typically this is small.
FEATURES
In terms of what an AS should do for you, have a browse of the Curity Concepts Pages. I work there, and we try to write about the science of OAuth and the common extensibility features software companies need.
CHOOSING YOUR MOMENTS
Integrating an AS and getting past all the blocking issues is a gradual journey though, and involves learning. So it requires choosing your moments, spikes and getting buy in from your stakeholders.
The main objective should always be simple and standard code in your apps, that is easy to scale. OAuth and the Authorization Server give you design patterns that help with this.
As said in OAuth2 rfc6749
The implicit grant type is used to obtain access tokens (it does not
support the issuance of refresh tokens) and is optimized for public
clients known to operate a particular redirection URI. These clients
are typically implemented in a browser using a scripting language
Refresh tokens are not suitable for implicit grant.
My question is:
How a mobile app, will refresh the access_token once it expires?
How the big ones in the market are doing this? Which practices they follow?
I know it is not following security recomendations, but it´s a good practice to make an long-lived access_token in this case? It can get annoying to need to re-authenticate each 30 min you use an app, or you close and reopen it.
As necessary permissions don´t change, a silent log-in on every app start, will be a choice to consider?
You don't necessarily need a refresh token to allow continued usage once an access token expires. If you must insist your clients use the implicit flow, then they may be able to make use of cookies and redirects to keep getting short-lived tokens without user interaction. Providing your client apps are using an HTTP agent which can use permanent cookies. e.g. apps that run in a web browser.
The key then is keeping the user signed into the identity provider the first time the token is requested.
This is done for example by the Identity provider (you I guess?) creating an HTTP cookie for the user agent to persist. Most big identity providers will do this - i.e. keep you signed in.
Now, when the token expires your client app will send the user back through the Oauth process again but, because the user has remained logged in to the identity provider, the identity provider can authenticate the user from the cookie without prompting for credentials.
If your clients instigate this token renewal on a background thread they can request the token as normal and, through the magic of HTTP redirects and cookies, get back a new token from you with no user action required.
Again - this alternative to refresh tokens relies on the client device being able to utilise permanent cookies, and your users remaining signed in and your auth server handling http cookies. If your clients are using native apps this solution may not work.
As in the future you will have 100s of clients maybe your auth plaform should offer different auth flows to different clients.
This article on mobile apps and implicit flow may be of interest to you.
Native apps are supposed to use the Auth code grant. So you can use refresh tokens. There is an RFC that discusses reasons (mainly security) for that as well as platform specific details. There is an important implication - the /token endpoint of your OAuth2 provider should not require authentication for getting tokens, because your application cannot keep its client secret safe.
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.
I'm trying to use OAuth with .NET (DotNetOpenAuth) to send updates to a Twitter account via a web application. I understand the basic workflow of OAuth and Twitter.
Where I'm confused if is it useful in a server web application? I don't want any user interaction.
But how it seems after an application start, the request token needs to be recreated and also an access token. This involves user interaction.
What is the correct workflow for my case?
Storing the request token or access token in config file?
Or the easist way, using HTTP basic authentication?
Thanks
If I understand you correctly your application will not be interacting with Twitter on behalf of your users but will be acting as the Twitter account for your application.
In this case there are 2 main factors to consider.
1) Do you want "from API" attached to each status as will be if you use basic auth or your applications name will happen if you use OAuth.
2) Do you want to put in the extra effort to implement OAuth.
If you decide to go with OAuth you would store your apps consumer key/secret and the accounts access token in configuration just like you would store the accounts screenname/password.
Your "request token needs to be recreated" phrase suggests you might be running into the problem where every time your user visits you need to re-authorize to Twitter, and perhaps you're looking for a way to access the user's Twitter account while he's not at your web site, and how can you do this when their token isn't fresh from being re-authorized. Is that right?
If so, the user isn't supposed to have to re-authorize Twitter every time they visit your site. The token is supposed to last a long time, which would also allow your site to access their Twitter account when they are not directly interacting with your web site. The problem may be that you haven't implemented the IConsumerTokenManager interface, but are instead using the default InMemoryTokenManager, which is for sample use only, since this memory-only token manager loses tokens every time the web app is restarted. Your own implementation of this simple interface should store and read the tokens out of some persistent storage such as a database.