DEX - attempt to use it as auth for services
TLDR: no, it is going to work only for full apps with authorization code flows, and won't work for cases when we need service to service communication
Usually when it comes to DEX it is mentioned as DYI solution for kubectl auth
But from what I see it is an almost complete OIDC implementation that may be used for auth between the services
From its getting started guide we gonna need:
git clone https://github.com/dexidp/dex.git
cd dex
make build
make examples
./bin/dex serve examples/config-dev.yaml
./bin/example-app
open http://localhost:5555
Use [email protected]
and password
for login button
The demo above starts DEX itself with sqlite storage and preconfigured client application
Dex, as OIDC does have discovery http://localhost:5556/dex/.well-known/openid-configuration
with all expected endpoints, including jwks, which means we should be able to consume it in dotnet for example like so:
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.JwtBearer;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization().AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.Authority = "http://127.0.0.1:5556/dex";
options.Audience = "example-app"; // using same audience as in given samples, coz it is checked by default
options.RequireHttpsMetadata = false; // just for local demo purposes
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", (ClaimsPrincipal user) => user.Claims.Select(c => new KeyValuePair<string, string>(c.Type, c.Value)).ToList());
app.Run();
curl http://localhost:5000 -H 'Authorization: Bearer paste_token_from_prev_step_here'
our jwt looks like this
{
"iss": "http://127.0.0.1:5556/dex",
"sub": "CiQwOGE4N...",
"aud": "example-app",
"exp": 1692439988,
"iat": 1692353588,
"at_hash": "GvkUlwJgjtMVHU4q79kIeg",
"email": "[email protected]",
"email_verified": true,
"name": "admin"
}
and response
[
{ "key": "iss", "value": "http://127.0.0.1:5556/dex" },
{ "key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "value": "CiQwOGE4Njg0Yi." },
{ "key": "aud", "value": "example-app" },
{ "key": "exp", "value": "1692439988" },
{ "key": "iat", "value": "1692353588" },
{ "key": "at_hash", "value": "GvkUlwJgjtMVHU4q79kIeg" },
{ "key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "value": "[email protected]" },
{ "key": "email_verified", "value": "true" },
{ "key": "name", "value": "admin" }
]
Dex - static clients
Even so there is sqlite storage the easiest way will be to configure clients manually via configuration file, so here is our edited config from getting started guide
issuer: http://127.0.0.1:5556/dex
storage:
type: sqlite3
config:
file: examples/dex.db
web:
http: 0.0.0.0:5556
# # will touch it little bit later
# frontend:
# issuer: dex
# logoURL: theme/logo.png
# dir: web/
# theme: light
telemetry: # http://localhost:5558/metrics
http: 0.0.0.0:5558
# # will touch it little bit later
# grpc:
# addr: 127.0.0.1:5557
# tlsCert: examples/grpc-client/server.crt
# tlsKey: examples/grpc-client/server.key
# tlsClientCA: examples/grpc-client/ca.crt
logger:
level: "debug"
format: "text"
oauth2:
passwordConnector: local # required for password flow
staticClients:
- id: example-app
redirectURIs:
- 'http://127.0.0.1:5555/callback'
name: 'Example App'
secret: ZXhhbXBsZS1hcHAtc2VjcmV0
- id: dotconsumer
name: 'dotnet example'
secret: HelloWorldMacWasHere2023
enablePasswordDB: true
staticPasswords:
- email: "[email protected]"
hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
username: "admin"
userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
- email: "[email protected]"
# bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
hash: "$2y$10$WXvGiM44DOAUVKSKJAaa1eeUZSF2vIPugPBBvGjD.j4Wm6P.UAQKK"
username: "mac"
userID: "1"
if everything done correct we should be able to login as [email protected]
using password
as password
also we have created our very first client and by default almost all flows are supported including password, so we should be able to:
curl -s -X POST http://127.0.0.1:5556/dex/token \
--data-urlencode "grant_type=password" \
--data-urlencode "client_id=dotconsumer" \
--data-urlencode "client_secret=HelloWorldMacWasHere2023" \
--data-urlencode "[email protected]" \
--data-urlencode "password=password" \
--data-urlencode "scope=openid"
and it did worked out
Note: make sure to uncomment passwordConnector
under oauth2
section for this to work
So far so good, but there is no client credentials flow or something like this, the only closes possible thing here is urn:ietf:params:oauth:grant-type:token-exchange
which is described here RFC 8693 OAuth 2.0 Token Exchange but it is not something we can use here, but still here is an example:
Step 1: retrieve id token somehow
id_token=$(curl -s -X POST http://127.0.0.1:5556/dex/token \
--data-urlencode "grant_type=password" \
--data-urlencode "client_id=dotconsumer" \
--data-urlencode "client_secret=HelloWorldMacWasHere2023" \
--data-urlencode "[email protected]" \
--data-urlencode "password=password" \
--data-urlencode "scope=openid" | jq -r ".id_token")
Step 2: exchange it
curl http://localhost:8080/api/token -d grant_type=urn:ietf:params:oauth:grant-type:token-exchange -d subject_token=$ID_TOKEN -d subject_token_type=urn:ietf:params:oauth:token-type:id_token -d client_id=5908895171 -d scope=email
curl -s -X POST http://127.0.0.1:5556/dex/token \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
--data-urlencode "subject_token=$id_token" \
--data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:id_token" \
--data-urlencode "client_id=dotconsumer" \
--data-urlencode "client_secret=HelloWorldMacWasHere2023" \
--data-urlencode "scope=openid"
But it won't work, because of missing connector_id
found in sources, the intent of this flow is similar to the way of how we did the trick with github actions and azure here - aka to exchange tokens between identity providers
Also the fun fact is that password flow is also missing from discovery endpoint
Reading closely some issues in dex github repo have found notes about it is not a supported way of using it and wont be, so in case of need it is recommended to use other tools or write own implementation