Suppose I have 2 services registered at the Auth Server:
Service A, with client-id=service-a-id and client_secret=service-a-secret
Service B, with client-id=service-b-id and client_secret=service-b-secret
Auth Server issues a JWT
Now service A wants to call service B and to use a client credentials flow.
Which of the services should share its client_secret shared with another?
If Service A uses its own secrets to send request to auth server and get a token, then service-a-secret should be shared with the Service B, so that it could verify the JWT signature?
I am quite disoriented because secret assumes not to be shared to anyone but auth server and owner application. However, if Service B wants to verify the token without calling Auth Server, what should it do.
Ok, it turns out that Auth Server signs JWT with its own keys and you do not need to know anyone's secret to validate the JWT. While it is pretty evident, it was not quite evident to me from the references.
So, client_secret MUST NOT be shared to anyone but Auth Server and Application, owning its secret.
Related
The goal is to get an access token from Keycloak to use that token for API calls.
The app should not require any login from the user, so it just need to authenticate itself.
I was planning to use client_credentials flow for that. However, client_credentials require the client to be confidential. And confidential clients have CORS issues in Keycloak.
If I switch to a public client I cannot use client_credentials flow anymore.
What is the best way to continue from here? Maybe I need to use password credentials flow and public client, because client credentials are going to be exposed anyway?
Create a new client, confidential, and activate service account on it.
You will be able to authenticate with grant_type=client_credentials using the client_id and client_secret as credentials (hence the service account, it's not a user account).
You will obtain an access token, no refresh token, and you'll simply have to reconnect again using the same credentials when the access_token will be expired.
For the permissions of this service account on the REST API check the 'scope' tab and the new 'Service Account' tab. You'll need access on some of the 'realm-managment' roles.
About creation new client application, it's not unusual to have several clients for the same real application, like you could have a bearer-only client for the API part, and a confidential one for other things. I do not know what is you CORS problems with confidential clients.
confidential clients are used by full stack applications (not front+back ones), and service accounts (B-to-B).
bearer_only is for API backs
public is only for front application (like angular, vuejs, etc) where you cannot store a client secret and the security depends only on the redirect_uri filter.
There's a helpful Microsoft doc that describes how to configure security for a daemon client application. This works ok but it means the client app must present a client id and client secret to the /token endpoint of AAD in order to obtain the OAuth2 access token.
This makes no use of managed identity and means I need to ensure the security of the client secret of the daemon app. If the client id and secret of this app were to fall into the wrong hands, there's nothing to prevent a bad actor obtaining an access token and calling the target service.
I realise that a certificate can be used instead of a client secret but my question is, can this be avoided through the use of the managed identity of the client daemon app?
I have a web app (C# / Javascript) where I want to call a back-end service that I own. I want to secure that service so only my app(s) can call it. Seems like if I use Oauth on the client side, the secret is exposed? All the docs I read about Oauth give solutions when the user of the app owns the resource, not when the app itself owns it. I was looking at how google apis work, and the JavaScript libraries seem to expose the key on the client side, no?
Yes you can accomplish this with OAuth, but how you go about it depends on the details of how the data accessed via your back-end service is organized. If the data is actually user-specific, then your user really is the resource owner. In this case you would use the typical authorization code grant. With this grant type you register a client with the OAuth auth server and receive a client_id and client_secret. The client_id is, indeed, exposed in the browser, but the client_secret sits in your web app server and is never exposed. It is only sent on back-channel (non-browser) requests to your auth server. The main thing here is that only your own client web app would be registered and receive the client_id/client_secret. You simply need to not provide any public registration endpoints so no other clients can register. With this grant type, in order for your web app to gain authorization to access the user's data on the back-end service, the user would need to approve the authorization in the browser as part of the process.
On the other hand if the data you're accessing on your back-end service is not user-specific, then you can use the OAuth Client Credentials grant. With this grant type you register the client as before and receive a client_id and client_secret. The secret is stored securely on your web app server and only passed in back-channel requests. You would avoid allowing any other clients to register. Your web app can then gain authorization to your back-end service without even needing any user authorization in the browser.
I'm afraid there is no way to restrict your API to be called just by the code of your applications. Browser applications with public codes cannot hold any secret (such as certificate), that would identify them, because anyone can extract it from the code. Desktop and mobile applications compiled to bytecode are not so easy to read, but with some effort, attacker could find the secret data. That's also the reason why these applications (so called public clients) don't hold client_secret if they act as OAuth2 clients. They use a one-time secret instead - PKCE.
What you can do, is to check the audience (what client ID the token was issued for) of an access token sent from a frontend application to your backend. You can get this info either from the token introspection endpoint (aud attribute) or from JWT attributes if the token is of JWT type.
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 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.