I am working on an web application. Which uses oauth to authenticate from different services.
Is there any risk of securing these tokens and secret directly into database. Or should I encrypt them ?
What are the general security pattern for saving oauth token and secret
This thread answers all of your questions:
Securly Storing OpenID identifiers and OAuth tokens
Essentially, the following are dependent among themselves one or other way:
Consumer key
Consumer secret
Access token
Access token secret
Unless the consumer key/secret are also at risk, you don't need to encrypt the access token/secret. The access tokens can only be used in combination with the consumer key/secret which generated them.
I'm assuming you're talking about the typical "Service Provider," "Consumer" and "User" setup?
If so, the session and cookies are good enough for saving tokens, but the problem is that it's your Consumers (your clients, as I understand) that need to be saving them and not you. Is there a session/cookie available in the scope of the calls to your API?
In either case, if the tokens are stored in the session or cookies, they will be "temporary" keys and the User will have to re-authenticate when they expire. But there is nothing wrong with that as far as the oAuth spec is concerned - as long as the Users don't mind re-authenticating.
Also bear in mind that the tokens are tied to a given service and user, and not to any IP address or device UUID, for example. They could not be used with different API and secret keys, as they are tied to the application they were issued for.
This way the user can de-authorize on a by-application basis, and every app can have a different set of permissions (e.g. read-only access). So your answer is you don't need to encrypt them, and you need them in plaintext anyway (if you're the User).
Related
I'm trying to systematize my knowledge about oauth + jwt + LDAP authorization. I've read multiple excellent articles (i.e. this) but still have a questions about about that:
My understanding:
JWT is a token which allow Single Sign-On (SSO). It's more secure than simple token auth since it encrypts all user specific info (e.g. userName, password, clientAppId, ip address etc.). This info is signed with internal authority server key and can't be changed by attacker.
From here, look at phrase below. As I understand that means that each of HTTP frontend servers doesn't require lookup for session data. But it requires lookup to authority server. What's the benefit? Isn't that the same single point of failure? Why JWT is considered STATEless? JWT still needs to keep user data on authority server, right?
The server side storage issues are gone.
If you need log out user with JWT before expiration period gone - you need to keep black lists. So what the benefit over simple token uath without SSO?
Is JWT a realization of OpenID (authentication only)?
It's impossible to do auto-sign-in for server-2-server with JWT (tokens) without OAuth. Oauth is used when you nwant ot authorize request from some service on behalf of user without user participation. Why it's impossible with tokens and possible with OAuth?
OAuth is also used to configure flexible access policies, like roles, groups etc. But why you can't implement them yourself based on tokens/JWT?
LDAP server is extremely fast for read operation on small not-interconnected pieces of data ,as user credentials. Where is LDAP in jwt-oauth scheme (or in OppenID Connect)? Is LDAP used for authentication (JWT)or authorization (OAuth)?
I'll try to clarify some concepts here:
Oauth and OpenID Connect (OIDC) are just authentication mechanisms by themselves. JWT is just a way to convey authenticated information between two parties. So, you have to do an effort of separation of concerns. When having doubts about how to identify an user, and be sure it's really him/her, check credentials and so... go check OIDC or Oauth standards. Whn in doubt about how to convey user related information between parties securely then, look at the JWT RFC and related (JWS, JWK, JWE and related).
Having said this:
Totally correct. You understood correctly.
It depends on implementation, but some stateful approaches exists, and also some implementations are stateless. The JWT-consuming server (Resource server in Oauth jargon), can possibly have the IdMS's (Authorization server (badly-named) in Oauth jargon) signing keys in cache, or pre-provisioned. This way, it can validate JWT Access Tokens coming from the IdMS without having to do any request. The IdMS could be down without impacting the system. This is precisely the case for some architectures that have the IdMS behind some VPN, and the Resource Servers outside it. Besides that, there could be a more stateful way of checking Access Tokens against the introspection endpoint of the IdMS. With this way, for each validation required on the Resource Server, a request would be made to the IdMS to check the Access Token is still valid and to extract the related claims. This latter mechanism is used also when the Access Tokens are not JWT and thus opaque.
Blacklists could be a way to do it, but it is more usually done through Refresh Token mechanism. You give the Access Token a very short lifetime, like 1 minute, and then rely on the refreshing mechanism to fail in case the session is revoked.
Technically speaking OpenID and OpenID Connect (OIDC) are different beasts. For shortness sake, we could say that OpenID is an old implementation of identity federation that did not see great adoption. OpenID Connect is an evolution of Oauth 2.0 that adds JWT, ID Token and some other niceties. But no, JWT and OIDC are by no means an exclusive implementation. It is true that OIDC implies forcefully the use of JWT, but JWT exists outside OIDC.
If you want to authorize requests between two servers, at the basic level, it can be done with simple tokens (Just maintain them secret, and use TLS). But with JWT what is enabled is that the servers can trust a central IdMS without having to trust entirely on each other. Oauth is used in this case you indicate because Google for example, trust himself and the user, but not your server. So, authentication occurs between Google, acting as the IdMS and the user, and this, generates a JWT (Not always, so you see the case for my previous statement) that your server (trusting an external IdMS) can use to communicate with Google.
As already said, groups/role management is independent of JWT/tokens used. JWT/plain tokens are only the way of conveying authentication information.
LDAP on Oauth/OIDC lies in the Authentication phase. When the user sends it's credentials to the IdMS instead of checking against a local database, the credentials are checked against LDAP. LDAP could also be used by some advanced IdMS's to retrieve policies, groups or other permissions. But when the authorization is done, the rest of the process is the same as always.
References:
https://openid.net/connect/
https://es.wikipedia.org/wiki/OpenID
https://www.rfc-editor.org/rfc/rfc7519#section-1
I am working on an application where scalability is a big concern. In the past I've used session-based authentication, but decided to go with a stateless server this time around in order to facilitate horizontal scaling.
I am not security expert, but in researching JWTs, it began to seem like these are very insecure. The whole reason we hash passwords is so that if our database is compromised, the attacker cannot impersonate a user. With JWT, we store a secret on the server. If the attacker gains access to the secret, can't they impersonate any user they want? Doesn't this mean that using JWTs would have the same level of security as storing plain text passwords?
I have read that people will sometimes use reddis to cross reference JWTs, but then the server isn't stateless, and I fail to see the benefit of using JWTs at all.
Could someone help clarify this issue for me?
Session based authentication systems, at least any that are worth using, also store a secret on the server. Just like the JWT, the secret is used to sign the data stored in the cookie that session based authentication uses. So this is no different than a JWT.
All of this is totally unrelated to password storage, as the password is only used when you don't have a cookie/JWT.
EDIT:
Not sure what to say about using Redis in conjunction with a JWT... What is being stored in Redis, the token? That seems pointless, as all the server needs to know is the secret to decode the token.
Here are some of the benefits to a using a JWT:
It's stateless, as you've already mentioned
It's not subject to CSRF/XSRF attacks. These attacks work by tricking your browser into sending the cookie to a server that didn't generate the cookie. This can't happen w/a JWT b/c the browser doesn't send the JWT automatically like it does w/cookies.
JWT's are standardized. There is a well defined way to generate them, which means that JWT's are more portable and the process has been vetted by the security community.
The server consuming a JWT token (resource server) does not need access to any secret. All it needs is the public key that belongs to the private key with which the token is digitally signed.
The authorization server that issues the token needs to keep its signing key secret obviously. But the nice thing about token based authentication is that this server can be created by an external party with much more resources/expertise to keep these things secret (Google, Facebook, Microsoft etc).
The resource server does not need to check the database to validate the token as you would need in case of username and password. This helps the scalability of the system and takes away a single point of failure.
If a client/user loses the JWT token, an attacker can impersonate the client/user until the token expires. A good reason to keep the lifetime of tokens short.
I don't see the point of storing JWT tokens in in a Reddis cache. There's no need to share tokens between servers as each call comes with a token in the Authorization HTTP header. Storing them in a cache only increases the risk of tokens being stolen.
I am building an intranet web application consisting of an Angular frontend and a Node.JS backend. The application needs to use the corporate Active Directory for authentication and authorization.
I'm considering how to best implement this in a secure way. I am planning to use the Active Directory node module for actually communicating with the AD to authenticate when the user logs in, and to check security group membership for certain restricted actions, etc.
However, I am not quite sure what is the best way to authorize my backend endpoints. The AD module does not offer any token/ticket, even though I suppose Kerberos is used for the actual authentication process. In other authenticated apps I've developed I've generated a jsonwebtoken when the user logs in, and then passed and verified that token in each backend route, is that a good idea also when authenticating against AD?
EDIT: Second part of question spawned to separate thread: Best practices for server-side handling of JWT tokens
Also, I have a more general concern, regarding what the best practice is for actually verifying tokens. Suppose that the "secret" used for JWT generation is compromised (in my scenario many people may have access to the source code of the system, but not to the system itself). Am I right in believing that a malicious user could then, with only this information, generate a token on behalf of any given user, and without ever authenticating with AD use that token in my API requests? A token is typically generated using jwt.sign(payload, secretOrPrivateKey, options).
Alternatively, suppose a malicious user could get hold of an actual token (before it has expired). To me it seems like instead of having to know a user's username and password, the security is now reduced to having to know the username and the JWT secret. Is this a valid concern and what should I do to prevent this?
My best hope so far is using a server side session to store information about the current user after logging in, so that even if a token is maliciously generated and used when accessing backend endpoints, it would fail unless the user has actually gone through the login route, authenticated with AD and stored some information in the session as a result of this.
I also considered actually authenticating with AD in each API endpoint, but that would require the AD username/password to be sent in every request, which in turn would require that sensitive information would have to be stored in the client's sessionstorage or localstorage, which is most likely a bad idea.
So, questions:
1) Is it reasonable to combine AD authorization with JWT as bearer token or what is the preferred way to build a secure backend + frontend utilizing AD for authentication?
2) If JWT is a good idea, what is the best practice for securing endpoints using JWT? Is using a server side session reasonable?
Interestingly enough I have found tons of examples on how to best implement token based authentication (in general, or with NodeJS specifically), but many of them seem flawed in one way or another.
1) Is it reasonable to combine AD authorization with JWT as bearer
token or what is the preferred way to build a secure backend +
frontend utilizing AD for authentication?
It is reasonable, but if you are already using Kerberos and AD to initially authenticate the user, you might consider using s4u2proxy constrained delegation which allows the service to present the user's service ticket to the KDC and acquire (subject to authorisation checks) a ticket for a backend service (and repeat for as many services are necessary).
If you have a lot of backend services that need to be contacted, a single JWT bearing all the authorization claims needed for all the services to enforce authorization policy may be a better option.
2) If JWT is a good idea, what is the best practice for securing
endpoints using JWT? Is using a server side session reasonable?
General key security practices apply:
Never store keys in the clear in non-volatile storage, anywhere.
Ideally do not store encrypted keys in attached storage on the server where, if the server is compromised, they would be subject to offline attack. Make them available to the host only at server startup.
Ensure key material resides in secure memory so that it cannot be swapped to disk (and/or use encrypted swap).
Use public key algorithms so that no secret key need exist on multiple hosts.
Consider using a hardware security module (HSM).
Am I correct that OAuth 1.0a credentials need to be stored in plaintext (or in a way that can be retrieved as plaintext) on the server, at least when doing 2-legged authentication? Isn't this much less secure than using a username and salted+hashed password, assuming you're using HTTPS or other TLS? Is there a way to store those credentials in such a way that a security breach doesn't require every single one to be revoked?
In more detail: I'm implementing an API and want to secure it with OAuth 1.0a. There will possibly be many different API clients in the future, but the only one so far has no need for sensitive user data, so I'm planning to use "2-legged" OAuth.
As I understand it, this means I generate a consumer key and a shared secret for each API client. On every API request, the client provides both the consumer key, and a signature generated with the shared secret. The secret itself is not sent over the wire, and I definitely understand why this is better than sending a username and password directly.
However, as I understand it, both the consumer and the provider must explicitly store both the consumer key and the shared secret (correct me if I'm wrong), and this seems like a major security risk. If an attacker breached the provider's data store containing the consumer keys and shared secrets, every single API client would be compromised and the only way to re-secure the system would be to revoke every single key. This is in contrast to passwords, which are (ideally) never stored in a reversible fashion on the server. If you're salting and hashing your passwords, then an attacker would not be able to break into any accounts just by compromising your database.
All the research I've done seems to just gloss over this problem by saying "secure the credentials as you would with any sensitive data", but that seems ridiculous. Breaches do occur, and while they may expose sensitive data they shouldn't allow the attacker to impersonate the user, right?
You are correct. oAuth allows you however to login on the behalf of a user, so the target server (the one you access data from) needs to trust the token you present.
Password hashes are good when you are the receiver of the secret as keyed-in by the user (which, by the way, is what effectively what happens when oAuth presents the login/acceptance window to the user to generate afterwards the token). This is where the "plaintext" part happens (the user inputs his password in plaintext).
You need to have an equivalent mechanism so that the server recognizes you; what oAuth offers is the capacity to present something else than a password - a limited authorization form the use to login on his behalf. If this leaks then you need to invalidate it.
You could store these secrets in more or less elaborated ways, at the end of the day you still need to present the "plaintext" version t the server (that server, however, may use a hash to store it for checking purposes, as it just needs to verify that what you present in plain text, when hashed, corresponds to the hash they store)
As far as I know, the OAuth standard is very lax on how OAuth really should behave, but...
I store OAuth access tokens for various OAuth services in a database. If these tokens were compromised, could they be used by a third party? I.e., are the given tokens bound to only my api and secret keys?
The tokens are tied to a given service and user. With those, one can pretend to be that user.
It is not tied to any IP address or device UUID for example (although one could do that as an additional precaution, but that is not part of OAuth).
If they were compromised, you'd deauthorize them, thus making them worthless.
could they be used with different API and secret keys?
No. The access token are also tied to the application they were issued for.
This way the user can de-authorize on a by-application basis, and every app can have a different set of permissions (e.g. read-only access).