Skip to content

Commit

Permalink
feat: add support for OIDC VC (#3575)
Browse files Browse the repository at this point in the history
This adds initial support for issuing verifiable credentials
as specified in https://openid.net/specs/openid-connect-userinfo-vc-1_0.html.

Because the spec is still in draft, public identifiers are
suffixed with `draft_00`.
  • Loading branch information
hperl committed Aug 4, 2023
1 parent eb89af7 commit 219a7c0
Show file tree
Hide file tree
Showing 39 changed files with 4,017 additions and 126 deletions.
6 changes: 6 additions & 0 deletions aead/xchacha20.go
Expand Up @@ -9,6 +9,7 @@ import (
cryptorand "crypto/rand"
"encoding/base64"
"fmt"
"math"

"golang.org/x/crypto/chacha20poly1305"

Expand Down Expand Up @@ -38,6 +39,11 @@ func (x *XChaCha20Poly1305) Encrypt(ctx context.Context, plaintext, additionalDa
return "", errorsx.WithStack(err)
}

// Make sure the size calculation does not overflow.
if len(plaintext) > math.MaxInt-aead.NonceSize()-aead.Overhead() {
return "", errorsx.WithStack(fmt.Errorf("plaintext too large"))
}

nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(plaintext)+aead.Overhead())
_, err = cryptorand.Read(nonce)
if err != nil {
Expand Down
11 changes: 4 additions & 7 deletions client/manager_test_helpers.go
Expand Up @@ -10,22 +10,19 @@ import (
"testing"
"time"

"github.com/go-faker/faker/v4"
"github.com/go-jose/go-jose/v3"
"github.com/gobuffalo/pop/v6"

"github.com/ory/x/assertx"
"github.com/ory/x/contextx"
"github.com/ory/x/sqlcon"

"github.com/bxcodec/faker/v3"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ory/fosite"

testhelpersuuid "github.com/ory/hydra/v2/internal/testhelpers/uuid"
"github.com/ory/hydra/v2/x"
"github.com/ory/x/assertx"
"github.com/ory/x/contextx"
"github.com/ory/x/sqlcon"
)

func TestHelperClientAutoGenerateKey(k string, m Storage) func(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions driver/config/provider.go
Expand Up @@ -42,6 +42,7 @@ const (
KeyOAuth2ClientRegistrationURL = "webfinger.oidc_discovery.client_registration_url"
KeyOAuth2TokenURL = "webfinger.oidc_discovery.token_url" // #nosec G101
KeyOAuth2AuthURL = "webfinger.oidc_discovery.auth_url"
KeyVerifiableCredentialsURL = "webfinger.oidc_discovery.verifiable_credentials_url" // #nosec G101
KeyJWKSURL = "webfinger.oidc_discovery.jwks_url"
KeyOIDCDiscoverySupportedClaims = "webfinger.oidc_discovery.supported_claims"
KeyOIDCDiscoverySupportedScope = "webfinger.oidc_discovery.supported_scope"
Expand All @@ -65,6 +66,7 @@ const (
KeyConsentRequestMaxAge = "ttl.login_consent_request"
KeyAccessTokenLifespan = "ttl.access_token" // #nosec G101
KeyRefreshTokenLifespan = "ttl.refresh_token" // #nosec G101
KeyVerifiableCredentialsNonceLifespan = "ttl.vc_nonce" // #nosec G101
KeyIDTokenLifespan = "ttl.id_token" // #nosec G101
KeyAuthCodeLifespan = "ttl.auth_code"
KeyScopeStrategy = "strategies.scope"
Expand Down Expand Up @@ -402,6 +404,10 @@ func (p *DefaultProvider) JWKSURL(ctx context.Context) *url.URL {
return p.getProvider(ctx).RequestURIF(KeyJWKSURL, urlx.AppendPaths(p.IssuerURL(ctx), "/.well-known/jwks.json"))
}

func (p *DefaultProvider) CredentialsEndpointURL(ctx context.Context) *url.URL {
return p.getProvider(ctx).RequestURIF(KeyVerifiableCredentialsURL, urlx.AppendPaths(p.PublicURL(ctx), "/credentials"))
}

type AccessTokenStrategySource interface {
GetAccessTokenStrategy() AccessTokenStrategyType
}
Expand Down
6 changes: 6 additions & 0 deletions driver/config/provider_fosite.go
Expand Up @@ -69,6 +69,12 @@ func (p *DefaultProvider) GetRefreshTokenLifespan(ctx context.Context) time.Dura
return p.getProvider(ctx).DurationF(KeyRefreshTokenLifespan, time.Hour*720)
}

var _ fosite.VerifiableCredentialsNonceLifespanProvider = (*DefaultProvider)(nil)

func (p *DefaultProvider) GetVerifiableCredentialsNonceLifespan(ctx context.Context) time.Duration {
return p.getProvider(ctx).DurationF(KeyVerifiableCredentialsNonceLifespan, time.Hour)
}

var _ fosite.IDTokenLifespanProvider = (*DefaultProvider)(nil)

func (p *DefaultProvider) GetIDTokenLifespan(ctx context.Context) time.Duration {
Expand Down
2 changes: 1 addition & 1 deletion driver/registry_base.go
Expand Up @@ -421,7 +421,7 @@ func (m *RegistryBase) OAuth2ProviderConfig() fosite.Configurator {
Config: conf,
}

conf.LoadDefaultHanlders(&compose.CommonStrategy{
conf.LoadDefaultHandlers(&compose.CommonStrategy{
CoreStrategy: fositex.NewTokenStrategy(m.Config(), hmacAtStrategy, &foauth2.DefaultJWTStrategy{
Signer: jwtAtStrategy,
HMACSHAStrategy: hmacAtStrategy,
Expand Down
3 changes: 1 addition & 2 deletions flow/flow_test.go
Expand Up @@ -7,12 +7,11 @@ import (
"testing"
"time"

"github.com/go-faker/faker/v4"
"github.com/mohae/deepcopy"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/bxcodec/faker/v3"

"github.com/ory/x/sqlxx"
)

Expand Down
3 changes: 2 additions & 1 deletion fositex/config.go
Expand Up @@ -58,6 +58,7 @@ var defaultFactories = []factory{
compose.OAuth2TokenIntrospectionFactory,
compose.OAuth2PKCEFactory,
compose.RFC7523AssertionGrantFactory,
compose.OIDCUserinfoVerifiableCredentialFactory,
}

func NewConfig(deps configDependencies) *Config {
Expand All @@ -68,7 +69,7 @@ func NewConfig(deps configDependencies) *Config {
return c
}

func (c *Config) LoadDefaultHanlders(strategy interface{}) {
func (c *Config) LoadDefaultHandlers(strategy interface{}) {
for _, factory := range defaultFactories {
res := factory(c, c.deps.Persister(), strategy)
if ah, ok := res.(fosite.AuthorizeEndpointHandler); ok {
Expand Down
26 changes: 16 additions & 10 deletions go.mod
Expand Up @@ -6,24 +6,28 @@ replace (
github.com/bradleyjkemp/cupaloy/v2 => github.com/aeneasr/cupaloy/v2 v2.6.1-0.20210924214125-3dfdd01210a3
github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.0.0
github.com/gobuffalo/packr => github.com/gobuffalo/packr v1.30.1
github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
github.com/mattn/go-sqlite3 => github.com/mattn/go-sqlite3 v1.14.13
github.com/oleiade/reflections => github.com/oleiade/reflections v1.0.1
github.com/satori/go.uuid => github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b
)

replace github.com/ory/hydra-client-go/v2 => ./internal/httpclient

// TODO(hperl): remove!
replace github.com/ory/fosite => github.com/ory/fosite v0.44.1-0.20230724105914-bc7e3385d777

require (
github.com/ThalesIgnite/crypto11 v1.2.4
github.com/bradleyjkemp/cupaloy/v2 v2.8.0
github.com/bxcodec/faker/v3 v3.7.0
github.com/cenkalti/backoff/v3 v3.2.2
github.com/fatih/structs v1.1.0
github.com/go-faker/faker/v4 v4.1.1
github.com/go-jose/go-jose/v3 v3.0.0
github.com/go-swagger/go-swagger v0.30.3
github.com/gobuffalo/pop/v6 v6.1.2-0.20230318123913-c85387acc9a0
github.com/gobwas/glob v0.2.3
github.com/gofrs/uuid v4.3.1+incompatible
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0
github.com/gorilla/securecookie v1.1.1
Expand Down Expand Up @@ -65,9 +69,9 @@ require (
go.opentelemetry.io/otel/sdk v1.11.1
go.opentelemetry.io/otel/trace v1.11.1
go.uber.org/automaxprocs v1.3.0
golang.org/x/crypto v0.10.0
golang.org/x/crypto v0.11.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/oauth2 v0.9.0
golang.org/x/oauth2 v0.10.0
golang.org/x/sync v0.3.0
golang.org/x/tools v0.10.0
)
Expand Down Expand Up @@ -229,16 +233,18 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.9.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.11.1 // indirect
go.opentelemetry.io/otel/metric v0.33.0 // indirect
go.opentelemetry.io/proto/otlp v0.18.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.11.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down

0 comments on commit 219a7c0

Please sign in to comment.