azure

package module
v0.0.0-...-4f31f5f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2021 License: MIT Imports: 10 Imported by: 0

README

go-jwt-azure

jwt-go signing methods backed by Azure Key Vault

Example

package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
	"github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault/keyvaultapi"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/adal"
	"github.com/Azure/go-autorest/autorest/azure"
	"github.com/golang-jwt/jwt/v4"
	jwtazure "github.com/shizhMSFT/go-jwt-azure"
)

func main() {
	// Extract parameters
	if len(os.Args) != 5 {
		fmt.Println("usage:", os.Args[0], "<tenant_id> <client_id> <secret> <key_id>")
		os.Exit(1)
	}
	tid := os.Args[1]
	cid := os.Args[2]
	secret := os.Args[3]
	kid := os.Args[4] // example: https://<keyvault_name>.vault.azure.net/keys/<name>/<version>

	// Get remote key
	client, err := getClient(tid, cid, secret)
	fail(err)
	key, err := jwtazure.NewKey(client, kid)
	fail(err)

	// Generate a JWT token
	token := jwt.NewWithClaims(jwtazure.SigningMethodPS512, jwt.MapClaims{
		"sub": "demo",
	})
	serialized, err := token.SignedString(key)
	fail(err)

	// Print the serialized token
	fmt.Println(serialized)

	// Parse and verify the token locally
	cert, err := key.Certificate()
	fail(err)
	_, err = jwt.Parse(serialized, func(token *jwt.Token) (interface{}, error) {
		if alg := token.Method.Alg(); alg != jwt.SigningMethodPS512.Alg() {
			return nil, fmt.Errorf("unexpected signing method: %v", alg)
		}
		return cert.PublicKey, nil
	})
	fail(err)

	// Parse and verify the token remotely
	jwt.RegisterSigningMethod(jwtazure.SigningMethodPS512.Alg(), func() jwt.SigningMethod {
		return jwtazure.SigningMethodPS512
	})
	_, err = jwt.Parse(serialized, func(token *jwt.Token) (interface{}, error) {
		if alg := token.Method.Alg(); alg != jwtazure.SigningMethodPS512.Alg() {
			return nil, fmt.Errorf("unexpected signing method: %v", alg)
		}
		return key, nil
	})
	fail(err)
}

func getClient(tenantID, clientID, secret string) (keyvaultapi.BaseClientAPI, error) {
	azureEnv := azure.PublicCloud
	oauthConfig, err := adal.NewOAuthConfig(azureEnv.ActiveDirectoryEndpoint, tenantID)
	if err != nil {
		return nil, err
	}
	spToken, err := adal.NewServicePrincipalToken(*oauthConfig, clientID, secret, strings.TrimSuffix(azureEnv.KeyVaultEndpoint, "/"))
	if err != nil {
		return nil, err
	}

	client := keyvault.New()
	client.Authorizer = autorest.NewBearerAuthorizer(spToken)
	return client, nil
}

func fail(err error) {
	if err != nil {
		panic(err)
	}
}

The above code outputs:

eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkZW1vIn0.iXopV96iaVk4i2_FefAr6v99LCdlSvjeiPGVUlwxX-9-Oo5MJIzqAtITbF30biuNrFeQs-nT_LD3yW85wuZXtAvtq1GQLEEUgbB7_RKgb04UGFne5keCaKuKeIzXVubF4-R9qrVnuyb9Igvu7eg_RdXm-Cr1V3OHEy49AlvKV3iDjam1_iChTZe2FywWcemjDK-0UBMRRxQDgdJuullkBwmtmPriaspF3Y3DSA7nZNGnHdkshrNPaImYo_uIRvuElToRCldD6XBUI5Czu1ax9rUR5VPw7kinF_RL-ETKu0H2mMaUnlKr6iI4yP4xjXdXBIuNpKs-VVOJkwkjRrhn4Q

The JWS compact object in the output can be pretty printed as

{
  "alg": "PS512",
  "typ": "JWT"
}.{
  "sub": "demo"
}.[Signature]

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidServerResponse = errors.New("azure: invalid server response")
	ErrMismatchResponseKeyID = errors.New("azure: response key id mismatch")
	ErrUnsupportedAlgorithm  = errors.New("azure: unsupported algorithm")
	ErrVerification          = errors.New("azure: verification error")
)

Common error

View Source
var (
	SigningMethodES256  = &SigningMethod{algorithm: keyvault.ES256}
	SigningMethodES256K = &SigningMethod{algorithm: keyvault.ES256K}
	SigningMethodES384  = &SigningMethod{algorithm: keyvault.ES384}
	SigningMethodES512  = &SigningMethod{algorithm: keyvault.ES512}
	SigningMethodPS256  = &SigningMethod{algorithm: keyvault.PS256}
	SigningMethodPS384  = &SigningMethod{algorithm: keyvault.PS384}
	SigningMethodPS512  = &SigningMethod{algorithm: keyvault.PS512}
	SigningMethodRS256  = &SigningMethod{algorithm: keyvault.RS256}
	SigningMethodRS384  = &SigningMethod{algorithm: keyvault.RS384}
	SigningMethodRS512  = &SigningMethod{algorithm: keyvault.RS512}
)

Specific instances of SigningMethod for a certain algorithms.

HashAlgorithms maps JWK signing algorithms to their corresponding hash algorithms.

SigningMethods maps JWK signing algorithms to their corresponding implementation.

Functions

func ComputeHash

func ComputeHash(algorithm keyvault.JSONWebKeySignatureAlgorithm, message []byte) ([]byte, error)

ComputeHash computes the digest of the message with the given hash algorithm.

Types

type Key

type Key struct {
	Client  keyvaultapi.BaseClientAPI
	Context context.Context
	// contains filtered or unexported fields
}

Key represents a remote key in the Azure Key Vault.

func NewKey

func NewKey(client keyvaultapi.BaseClientAPI, keyID string) (*Key, error)

NewKey create a remote key referenced by a key identifier.

func NewKeyWithContext

func NewKeyWithContext(ctx context.Context, client keyvaultapi.BaseClientAPI, keyID string) (*Key, error)

NewKeyWithContext create a remote key referenced by a key identifier with context.

func (*Key) Certificate

func (k *Key) Certificate() (*x509.Certificate, error)

Certificate returns the X.509 certificate associated with the key.

func (*Key) Sign

func (k *Key) Sign(algorithm keyvault.JSONWebKeySignatureAlgorithm, message []byte) ([]byte, error)

Sign signs the message with the algorithm provided.

func (*Key) SignDigest

func (k *Key) SignDigest(algorithm keyvault.JSONWebKeySignatureAlgorithm, digest []byte) ([]byte, error)

SignDigest signs the message digest with the algorithm provided.

func (*Key) Verify

func (k *Key) Verify(algorithm keyvault.JSONWebKeySignatureAlgorithm, message, signature []byte) error

Verify verifies the message with the algorithm provided against the signature.

func (*Key) VerifyDigest

func (k *Key) VerifyDigest(algorithm keyvault.JSONWebKeySignatureAlgorithm, digest, signature []byte) error

VerifyDigest verifies the message digest with the algorithm provided against the signature.

type SigningMethod

type SigningMethod struct {
	// contains filtered or unexported fields
}

SigningMethod for Azure Key Vault.

func (*SigningMethod) Alg

func (m *SigningMethod) Alg() string

Alg identifies the signing / verification algorithm. For more information on possible algorithm types, see https://docs.microsoft.com/en-us/rest/api/keyvault/sign/sign#jsonwebkeysignaturealgorithm

func (*SigningMethod) Sign

func (m *SigningMethod) Sign(signingString string, key interface{}) (string, error)

Sign signs the signing string remotely.

func (*SigningMethod) Verify

func (m *SigningMethod) Verify(signingString, signature string, key interface{}) error

Verify verifies the singing string against the signature remotely.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL