Protecting client credentials for (multi-tenant) application should be your highest priority, not only in production also during development.
We developed a small application that helps you do just that. Use your Visual Studio credentials to sign a token request while the certificate stays in the KeyVault. You could even only authorize developers to use the certificates in a KeyVault when they need it and de-authorize then when it’s no longer needed.
Client credentials
So you’re developing an application that talks to Microsoft Graph or your custom api. You’re probably using postman or Insomnia to test the api.
Postman and Insomnia are great, but they doesn’t support using certificates as client credentials. So you’ll always need to create a client secret in the app registration. That secret is probably configured on the local machines of all the developers. Not really secure. Especially not if that application registration is also used in production. If all your developers already sign-in to Visual studio, the probably have credentials configured that might just work to access a resource in azure.
Introducing KeyVault token proxy
We build a small open-source dotnet tool that uses the credentials already available to the developer to securely connect to a KeyVault and get a token with certificate in KeyVault.
- Install token proxy
dotnet tool install --global Smartersoft.Identity.Client.Assertion.Proxy
- Start proxy from command line
az-kv-proxy
- Browse the swagger documentation at
http://localhost:{port}/swagger/index.html
See documentation
Request an access token
Once you have this proxy running you have several ways to get a token for some application. To use this proxy it requires you to create a certificate in the KeyVault and adding that to an application registration.
Gather the required data:
Parameter | Sample | Description |
---|---|---|
clientId |
996ba276-df43-40af-8ffd-d1564b1c88a8 |
The ID of the application you’re trying to use |
tenantId |
d198b314-13c1-4ad1-8526-92355369ec6c |
The ID of the tenant you want a certificate for |
scopes |
https://graph.microsoft.com/.default |
The scope where you want to get a token for |
Depending on which method you’re using you’ll need some extra information.
- Get token using KeyVault key
- Get token using KeyVault certificate *less efficient**.
- And if you want to use a certificate from the local cert store that is also possible, but won’t add a lot security wise.
Pick the endpoint that you like best, and use it in the description for Insomnia or Postman
Use KeyVault token proxy with Insomnia
I personally use Insomnia as a rest api test tool, it suits my needs and seems to work quite intuitively. To use the KeyVault token proxy in Insomnia just follow along.
- Create a new
POST
request to your token endpoint/api/token/kv-certificate
in this case. - Set the required
JSON
body, I’m using variables here, but you can also configure it statically. - Try the request with the Send button
- Create a new request to the api, where you want to use the token.
- Set the authentication to
Bearer
- In the token field, press
CTRL + SPACE
and selectResponse => Body attribute
- Double click the now red configuration.
- Select the token request, set Filter:
$.accessToken
, Trigger behavior:When expired
and max age:3500
. It should now show a token in the Live Preview window.
Everytime you try to execute this request it will automatically get a token (if it was expired) as long as the proxy is running.
Use KeyVault token proxy with Postman
You can also use this proxy with postman. Someone else already made a great post on how that should work, see this postman blog.
Like it?
If you really like this proxy or if you have a very good reason why this is a bad idea, please let me know.
Dotnet tool
I never build a dotnet tool so this was also a nice experiment. The resulting tool is a small web api with swagger ui, packaged as a dotnet tool. This is published through nuget.
Creating a dotnet tool is a great way to package a small command line application. To create a dotnet tool package from an existing dotnet core application you only need to add a few lines to your project file and call dotnet pack
.