Cert bound sts server - Certificate Bound Tokens using Security Token Exchange Server (STS)

Certificate Bound Tokens using Security Token Exchange Server (STS)

Sample demonstration of Certificate Bound Tokens acquired from a Security Token Exchange Server.

The basic idea behind bound tokens is that the signed bearer token (eg JWT) itself has information embedded within it which defines the transport/TLS client certificate that must be present for the token to be valid in.

For example , suppose you want to say "only trust this JWT if it is presented within an mTLS context that used a specific client certificate.

Binding the token to the cert reduces the security risk of bearer tokens since nobody can reuse the bearer token without the client certificate

As an example, consider an application is in possession of a client certificate with the following hash:

$ openssl x509 -in certs/alice.crt -outform DER | openssl dgst -sha256 | cut -d" " -f2
492d412c90b7d1747f02583d03dbf52e009fde113dd454bd5de572bde6595efc

$ echo "492d412c90b7d1747f02583d03dbf52e009fde113dd454bd5de572bde6595efc" | xxd -r -p - | openssl enc -a 
SS1BLJC30XR/Alg9A9v1LgCf3hE91FS9XeVyveZZXvw=

If JWT token is issued with the following standard claim:

{
  "alg": "RS256",
  "kid": "b9b8c3e23bb5d95c1520049e8824f9105cc207e",
  "typ": "JWT"
}
{
  "aud": "https://server.domain.com:8443",
  "exp": 1671834129,
  "iat": 1641075729,
  "iss": "https://sts.domain.com",
  "sub": "alice",
  "cnf": {
    "x5t#S256": "SS1BLJC30XR/Alg9A9v1LgCf3hE91FS9XeVyveZZXvw="
  }
}

then an application can only consider that token to be valid if the mTLS session context contains the hash of the client cert's public key as shown. In other words, once mTLS is setup with the server, the TLS certificate is hashed and compared to the claims. This way, even if the JWT token is stolen, it can't be used without the client cert.


Background

OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens rfc 8705 describes a mechanism where a specific specific claim in a JWT bearer token presented to a server includes the hash of the public certificate that is authorized and corresponds to the mTLS certificate currently used during the connection.

For example, if the public cert used by the client is certs/alice.crt, then the thumbprint is calculate as such and gets included into the JWT by the token issuer

3.1.  JWT Certificate Thumbprint Confirmation Method

   When access tokens are represented as JSON Web Tokens (JWT)[RFC7519],
   the certificate hash information SHOULD be represented using the
   "x5t#S256" confirmation method member defined herein.

   To represent the hash of a certificate in a JWT, this specification
   defines the new JWT Confirmation Method [RFC7800] member "x5t#S256"
   for the X.509 Certificate SHA-256 Thumbprint.  The value of the
   "x5t#S256" member is a base64url-encoded [RFC4648] SHA-256 [SHS] hash
   (a.k.a. thumbprint, fingerprint or digest) of the DER encoding [X690]
   of the X.509 certificate [RFC5280].  The base64url-encoded value MUST
   omit all trailing pad '=' characters and MUST NOT include any line
   breaks, whitespace, or other additional characters.

Which eventually is sealed into a bearer token (JWT in this case) using the following claim:

{
  "cnf": {
    "x5t#S256": "SS1BLJC30XR/Alg9A9v1LgCf3hE91FS9XeVyveZZXvw="
  }
}

For more information, see


This repo shows how to setup a sample STS server that checks the mtls connection and returns a bound JWT. The resource REST server can verify the mtls session against the presented JWT:

images/bound_token.png

Setup

First override the hosts value as shown below. This is done just for TLS SNI simplicity

/etc/hosts:

127.0.0.1  grpc.domain.com sts.domain.com server.domain.com

STS server

Run the STS server.

The keyID is just an opaque hash of the sts.crt's public key and just use in the JWK (in reality, it can be any value since its just used to lookup the key in jwk.json

cd sts_server/
go run sts_server.go --port :8081 --tlsCA ../certs/tls-ca.crt \
  --tlsCert ../certs/sts.crt --tlsKey ../certs/sts.key \
  --jwtPrivateKey ../certs/jwt.key --jwtKeyID b9b8c3e23bb5d95c1520049e8824f9105cc207e

curl

You can test the STS server by itself by using curl and mTLS:

# test as alice
$ curl -s -X POST -H "Content-Type: application/json" -d @curl/sts_req_alice.json  \
    -H "host: sts.domain.com"   --resolve  sts.domain.com:8081:127.0.0.1 \
    --cert certs/alice.crt    --key certs/alice.key  \
    --cacert certs/tls-ca.crt   https://sts.domain.com:8081/token | jq '.'

# test as bob
$ curl -s -X POST -H "Content-Type: application/json" -d @curl/sts_req_bob.json  \
    -H "host: sts.domain.com"   --resolve  sts.domain.com:8081:127.0.0.1 \
    --cert certs/bob.crt    --key certs/bob.key  \
    --cacert certs/tls-ca.crt   https://sts.domain.com:8081/token | jq '.'

The JWT returned has the certificate hash burned into it as shown in the claims above.

REST

To test REST, first run the backend server

cd http/
go run src/server/server.go --port :8443 --tlsCA ../certs/tls-ca.crt  \
    --tlsCert ../certs/server.crt \
    --tlsKey ../certs/server.key --jwkFile ../certs/jwk.json

Then run the client

go run src/client/client.go --tlsCA ../certs/tls-ca.crt  \
    --tlsCert ../certs/alice.crt \
    --tlsKey ../certs/alice.key --stsaddress https://sts.domain.com:8081/token

What the client does on startup is contact the STS server over mTLS.

It then presents the initial token for the client

The STS server checks the mTLS client certificate, extracts its hash, and then if the initial token is valid, it will reissue a new JWT but one with the certificate hash burned into the claim.

From there, the client will emit that token to the resource server again over the mTLS using the same client certificate it used on the STS server The resource will check the JWT, extract the claims that describes the client cert its bound to and then check the actual TLS context for the certificate presented.

If all goes well, the api call is allowed through.

If you want to test a failure, you can uncomment the code section in client.go which tries to use alice's bound token with bob's client certificate. This second api call should fail since there is a mismatch

gRPC

gRPC natively support STS credentials see grpc.credentials.sts.

I began to write a simple client server similar to REST that used STS and certificate bound tokens but ran into an issue:

When gRPC contacts an STS server on its own, it does NOT use client certificates and simply uses the generic http TLS system certs:

see sts.go

This is problem since the STS server needs to know about the client cert for all this to work anyway.

For now, i've just left the code in as-is even though its not working

echo -n iamtheeggman > /tmp/cred.txt

go run src/grpc_server.go --grpcport :50051 \
   --tlsCert ../certs/grpc.crt \
   --tlsKey ../certs/grpc.key \
   --tlsCA ../certs/tls-ca.crt  \
   --jwkFile ../certs/jwk.json

go run src/grpc_client.go --host localhost:50051 \
   --servername grpc.domain.com --tlsCA ../certs/tls-ca.crt \
   --tlsCert ../certs/alice.crt --tlsKey ../certs/alice.key \
   --stsaddress https://sts.domain.com:8081 --stsCred /tmp/cred.txt \
   --stsSNIServerName sts.domain.com

Embedding private keys into Hardware

In the example above, the TLS certificates are plain PEM files on disk. Users are free to embed the mTLS certificate into Hardware like Trusted Platform Module (TPM) or Yubikey or other HSMs. That way, at least the client certificate is more secure.

For additional information, see:

Similar Resources

A tool for capturing newly issued x.509 from Certificate Transparency logs & performing periodic revocation checking.

ct-logster This repository contains the tools for collecting newly issued x509 certificates from Certificate Transparency logs, as well as performing

May 4, 2022

Simple web content/proxy server that embodies enterprise zero trust security

pswa - Protected Static Web App Introduction pswa is a simple web content/proxy server which is suitable for various static web apps. Features Availab

Nov 11, 2022

A client software for acme-dns with emphasis on usability and guidance through setup and additional security safeguard mechanisms

acme-dns-client A client software for acme-dns with emphasis on usability and guidance through setup and additional security safeguard mechanisms. It

Dec 2, 2022

Hetty is an HTTP toolkit for security research.

Hetty is an HTTP toolkit for security research.

Hetty is an HTTP toolkit for security research. It aims to become an open source alternative to commercial software like Burp Suite Pro, with powerful

Dec 27, 2022

This application demonstrates how to launch high-performance "serverless" functions from the YoMo framework to process streaming data. The functions are embedded in a WebAssembly VM, WasmEdge, for safety, security, portability, and manageability.

This application demonstrates how to launch high-performance

Streaming Image Recognition by WebAssembly This project demonstrates how to process a video stream in real-time using WebAssembly and apply a pre-trai

Nov 9, 2022

Automatic AWS Security Group ingress through DDNS

Auto DDNS Security Lambda Update AWS Security Group rules to an IP resolved from a DNS hostname. Useful to dynamically allow ingress from a DDNS hostn

Oct 19, 2021

Scout is a standalone open source software solution for DIY video security.

Scout is a standalone open source software solution for DIY video security.

scout Scout is a standalone open source software solution for DIY video security. https://www.jonoton-innovation.com Features No monthly fees! Easy In

Oct 25, 2022

This service is intented to collect data using grpc using Go lang backend and cassandra DB as storage

Go Data Collection This service is intented to collect data using grpc using Go lang backend and cassandra DB as storage. Dev Setup make test_env make

Apr 13, 2022

Cross-platform, multi-server chat app built using Fyne

Cross-platform, multi-server chat app built using Fyne

Fibro Really early days proof of concept for a cross-platform multi-server chat. Feel free to play, but don't expect it to do much! Features Multiple

Sep 10, 2022
Comments
  • remove github.com/lestrrat/go-jwx

    remove github.com/lestrrat/go-jwx

    Background: I'm trying to delete github.com/lestrrat/go-jwx (not to be confused with github.com/lestrrat-go/jwx) for good, and I'm going over the dependents list in my spare time. Your repository was using this very obsolete library, so I have created what I think would be a fix.

    You certainly do not have to accept this PR by any means, but please understand that github.com/lestrrat/go-jwx might be deleted some time in the future.

    Thanks.

Openstack Invalid HTTPS Cert Scanner

Openstack Invalid HTTPS Cert Scanner Scans all OpenStack API endpoints in a given catalog and warns about legacy HTTPS certificates that do not list t

Jan 18, 2022
Tscert - Minimal package for just the HTTPS cert fetching part of the Tailscale client API

tscert This is a stripped down version of the tailscale.com/client/tailscale Go

Nov 27, 2022
Sixmap - Tool to visualize the SIX (Seattle Internet Exchange) route server coverage

Mapping the SIX route server This program generates an IPv4 map. In particular,

Nov 9, 2022
An IPFS bytes exchange for caching and retrieving data from Filecoin

?? go-hop-exchange An IPFS bytes exchange to allow any IPFS node to become a Filecoin retrieval provider and retrieve content from Filecoin Highlights

Aug 25, 2022
Go client for the Foreign exchange rates and currency conversion API 💰

fixer Go client for Fixer.io (Foreign exchange rates and currency conversion API) You need to register for a free access key if using the default Fixe

Nov 14, 2022
Toy TLS certificate viewer

veilig Toy tls certificate viewer that I built because openssl s_client confuses me Source available at: https://github.com/noqqe/veilig/ Please repor

Aug 25, 2022
Go decoder for EU Digital COVID Certificate (EUDCC) QR code data

Go Corona QR Code Decoder This repository contains a decoder for EU Digital COVID Certificate (EUDCC) QR code data, written in Go. If you got vaccinat

Nov 30, 2022
DNS/DoT to DoH proxy with load-balancing, fail-over and SSL certificate management

dns-proxy Configuration Variable Example Description TLS_DOMAIN my.duckdns.org Domain name without wildcards. Used to create wildcard certificate and

Oct 26, 2022
EU Digital Covid Certificate utilities in Go [Create, Validate and Parse Green-Pass/EU-DCC]

go-dcc EU Digital Covid Certificate utilities in Go [Create, Validate and Parse Green-Pass/EU-DCC] Repo work in-progress CLI Usage: ######Create and S

Dec 23, 2021
A CLI tool to get Certificate Transparency logs of a domain name.
A CLI tool to get Certificate Transparency logs of a domain name.

crt crt is a CLI tool to get Certificate Transparency logs of a domain name. It can also enumerate subdomains. Installation If you have Go installed:

Dec 17, 2022