I was reading an article about OAuth 2.0 with jwt tokens. Interesting part is when author describes client_secret, he says:
In a non-trivial implementation client ids and passwords will be securely stored in a database and retrievable through a separate API that clients applications access during deployment.
Now let's say I have a frontend app in angular and a backend app in spring with MySQL db.
My question is what author meant by the aforementioned quote. Is it, that
client (frontend app in this case) makes a call using client_id
and secret (nothing changes here), but backend is checking
provided "credentials" not by comparing with values stored in plain-text (in
application.properties in that case), but making a hash from received values and
comparing with hashed version in db ?
EDITED:
User john doe opens log in page. Provides credentials: username:john.doe and password:john1. Clicks sign in.
Angular-frontend intercepts request, and executes a method (f.e. obtainTokenForUser()) in order to get a short-period-valid jwt token for the user. For that reason angular-app sends an OAuth2.0-compliant request to the authorization server. Before sending contant AWS KMS to get its client_id and secret in order to attach to the request. In the end, the request from angular to auth server looks like: curl front-app-sp3:frnt4pP#<auth_server_ip_addr>:<auth_server_port>/oauth/token -d grant_type=password -d username=john.doe -d password=john1
Authorization server contacts AWS KMS for received client_id:front-app-sp3 and client_secret:frnt4pP. It finds the entry, passwords matches, validation correct. Auth server generates a JWT token valid f.e. 5 minutes. The token is signed by the server using AS_pr1v4t3 private key. Authorization server returns a token to angular app.
User is logged in. User requests a resource in the main app (in spring), thus angular adds an obtained token and sends the request to the "Main-web application".
Resource server in the "Main-web application" validates token. Token is correct and valid. Resource is returned.
I don't think that's what the author is referring to. He is talking about instead of having client_id and client_secret in your application.properties they are to be stored in a DB which your backend can access through a different API. I would argue that the client_id belongs more to the application.properties than the secret management service though. Your front-end (angular app in this case) should never have access to client-id or the secret. Your server which the angular app is connected to (through some REST services I imagine) should never have direct access to the secrets either, it should go through a separate secret management API. It's ok for your server to have the client_id in the application properties, but the secret should be stored in a very secure place.
This is an already implemented pattern though. Instead of having the secret values directly in the app.config / application.properties file you should have them in something like:
AWS Key Management Service
Azure Key Vault
These would allow you to store / update / retrieve and rotate your secrets.
Related
I write a rest api with yii2 and i am using oAuth2 , the problem is when user want login , client web application should send request to get token , request should contain client_id and secret_key and username and password in this case user can simply inspect element and click to network and see posted parameter to the server this means user can see client_id and secret_key.
client_id and secret_key are signature for each application and server can find out witch application use api.
how to handle this security issue?
It seems you have missed out one key element of OAuth 2.0, client type.
OAuth 2.0 defines two types of clients, public clients and confidentiatl clients.
2.1. Client Types
confidential
These are the clients which can protect a credential. They have the
full potential to use authorization code grant type, which obtain
token from backchannel request. Because they use backchannel to obtain
tokens, their credentials are never exposed to end user(via user
agent)
public
Clients which cannot protect credentials. For example SPA clients and
mobile apps comes to this category.
In your case, you seems to have a public client (user agent based application in broswer as it seems). In such case, you should set your client type to a public client. If this is not the case, you are not utilizing a proper back channel call from your web application.
Additionally, public clients which use authorization code flow can use PKCE to avoid authorization code theft attacks. Related RFC can be found from RFC7636
I am trying to implement token based authorization in rails, with devise_token_auth (https://github.com/lynndylanhurley/devise_token_auth#conceptual).
When I post uid and password against sign_in method, it returns access-token, client (and uid itself) in header. I understand that token based authorization works like this:
User posts uid(id) and password to api server.
Api server validates the uid and password
Issues Token and returns it, if the uid and password matched.
Client receives the Token.
Client whenever client wants to access the authentication required apis, Client uses the uid and the Token in order to prove that this client is in fact already authenticated.
I can understand that access-token corresponds to the Token described in above explanation. That leads to me a question of what the client header value is, because it seems that, according to the official Wiki (https://github.com/lynndylanhurley/devise_token_auth#usage-tldr), devise_auth_token library not only use requires access-token but also client value.
Question:
In devise_token_auth, what is the purpose of client header value? Why is it also needed for identifying the user? Couldn't that be included in (or, concatenated to) the access-token value?
The client header is generated for every different device accessing the API. Its purpose is to maintain more than one session active for a specific user (web client, mobile client, etc.).
You can test this by signing in with the same user on 2 separate web clients and checking user.tokens, there should be 1 set of tokens for every client.
I am new to Hashicorp Vault. I was hoping to secure my client id and secret for an OAuth2 Password Flow using Hashicorp Vault. Each time my backend REST API is called, it requires the client id and secret, as well as the user credentials of username and password. How would I do this in a secure way and only let my app pass this without disclosing this in my javascript client?
Thanks.
John
If I read your question correctly, you have a Javascript application that calls your own (REST) backend service. That call is secured using a client id, client secret, username ánd password. That raises a couple of issues:
client id and secret, as well as the user credentials of username and password
That seems like the wrong approach to take: an OAuth-secured resource (your REST backend service) should not require a username and password. Logging in the user is done in the authorization server.
Try starting with reading the OAuth2-spec (RFC 6749) or the DigitalOcean tutorial for a comprehensive overview.
How would I do this in a secure way and only let my app pass this without disclosing this in my javascript client?
You can't: client secrets cannot be protected in a client-controlled application because an evil client can reverse-engineer your application (or read your javascript). What you have is called a "public client", i.e. a client that cannot keep its secret confidential. In this case, you don't use client secrets. Try starting with this question or the introduction to oauth2 client types.
I have a multiple microservices architecture in which I intend to apply security.
My View of the Security Design:
The authentication will happen with an LDAP and when the user is authenticated a JSON Web Token (JWT) will get generated using a "secret key" and the token will have the roles, expiration time etc. With every call to a microservice this token will be passed in Header for authorization. In my view I just have one single auth server which authenticates the user and generates the JWT.
My Doubt:
Now, when a microservice will receive a call (containing the JWT in Header) will it always hit the auth server to get the token verified?
If yes, won't it lead to multiple calls to auth server and thus a bad practice?
If no, how will the client verify the token and what is the scope of the auth server?
JWTs are always signed, so that you can verify a given token without doing a call to some central auth instance. The auth server knows the secret to sign the token and all services that want to validate the token also need have a way to check this.
There are two different approaches to signing:
symmetric: A secret value is appended before hashing the payload. The consuming service also needs to know this secret and can verify by appending the secret to the payload received and checking the resulting hash with the transmitted hash.
asymmetric: By using some PKI signing/verification it is possible that only the auth server has the private key to sign the token. All consuming services then only need the public part to verify.
I prefer the second way, cause it reduces the chance of a key getting stolen. If one of the consuming services is hijacked, there is no secret lost such that the attacker can create valid tokens. Using such an algorithm could possibly take some more time / cpu cycles for validating than a simple hash used in the symmetric way.
Please see the official JWT page for an example of the different mechanisms: https://jwt.io/
I have been trying to understand how OAuth2 works. At first I thought it was redundant to spend one extra step exchanging auth code + client secret for access token - why not have server return access token directly. For that I found this explanation.
Then what confuses me is, why does it need a clientId and a client secret, instead of just a secret? A secret which can both declare and prove itself. The client app then can simply pass it to server when it sends user there to authorize itself for accessing server resource.
Thanks!
Imagine the client signs the request with the secret and sends just the signature. How does the server know which secret to use? Presumably the server supports multiple consumers.
The client id is sent in the first part of the token dance to identify the client. This id is sent in an insecure way, in the URL. Even on the authz server end of this request the id may be exposed in an insecure way where the authz server redirects the user agent to the authorization page. So the client id is not meant to be secure, just to identify the client.
Only after receiving the authorization code (after user authorization), does the client then need to obtain the access token in a more secured way. This is where the client secret is used over TLS.
You can have the server return the access token directly. You need to request Implicit grant (response_type with the value token instead of code).
The authorization server returns the access token directly.
This type of grant is intended to be used for user-agent-based clients (e.g. single page web apps) that can’t keep a client secret or client id because all of the application code and storage is easily accessible. If your client can keep a secret, it is recommended that you use a more secure grant type.