Skip to content
This repository has been archived by the owner on Apr 11, 2023. It is now read-only.

Commit

Permalink
feat: return subject ID in gnap auth&continue responses
Browse files Browse the repository at this point in the history
Fixes: #249

Signed-off-by: Filip Burlacu <[email protected]>
  • Loading branch information
Filip Burlacu committed Jun 24, 2022
1 parent 852f8d5 commit 1b9a649
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 56 deletions.
2 changes: 1 addition & 1 deletion cmd/auth-rest/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 // indirect
github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 // indirect
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af // indirect
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.0.2 // indirect
github.com/xdg-go/stringprep v1.0.2 // indirect
Expand Down
5 changes: 2 additions & 3 deletions cmd/auth-rest/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
Expand All @@ -787,8 +786,8 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af h1:gnMi90yPlM5iBq4W8sGCQ/x0cFpv7k40wT8SQHKxBfU=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af/go.mod h1:BPAXixzwWfMHm55daYibYOD4Aq6UO0wCIKZMZYAvsTk=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136 h1:zdkrPZHa9Uzo46bF/JHHklfD/Y8vJBzcrwHNE4LKo54=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136/go.mod h1:v5BbFh80GLt8+uaiNLcoOr1IqBGkkZUvazleuimmGdc=
github.com/trustbloc/edge-core v0.1.8 h1:m4X5XNDwiHJjGf8gHnpo6aLkBYuqDyNRq+npjxLc5cY=
github.com/trustbloc/edge-core v0.1.8/go.mod h1:gfoyG/xquRXyHkww0ldM2jwOTuKKZpHYn+87f+TBQ8M=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ require (
github.com/hyperledger/aries-framework-go/spi v0.0.0-20220330140627-07042d78580c
github.com/ory/hydra-client-go v1.10.6
github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693
github.com/stretchr/testify v1.7.1
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af
github.com/stretchr/testify v1.7.2
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136
github.com/trustbloc/edge-core v0.1.8
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
Expand Down Expand Up @@ -61,5 +61,5 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
11 changes: 6 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -659,8 +659,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4/go.mod h1:9PdLyPiZIiW3UopXyRnPYyjUXSpiQNHRLu8fOsR3o8M=
github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 h1:RBkacARv7qY5laaXGlF4wFB/tk5rnthhPb8oIBGoagY=
Expand All @@ -671,8 +671,8 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af h1:gnMi90yPlM5iBq4W8sGCQ/x0cFpv7k40wT8SQHKxBfU=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af/go.mod h1:BPAXixzwWfMHm55daYibYOD4Aq6UO0wCIKZMZYAvsTk=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136 h1:zdkrPZHa9Uzo46bF/JHHklfD/Y8vJBzcrwHNE4LKo54=
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136/go.mod h1:v5BbFh80GLt8+uaiNLcoOr1IqBGkkZUvazleuimmGdc=
github.com/trustbloc/edge-core v0.1.8 h1:m4X5XNDwiHJjGf8gHnpo6aLkBYuqDyNRq+npjxLc5cY=
github.com/trustbloc/edge-core v0.1.8/go.mod h1:gfoyG/xquRXyHkww0ldM2jwOTuKKZpHYn+87f+TBQ8M=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
Expand Down Expand Up @@ -1190,8 +1190,9 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
112 changes: 83 additions & 29 deletions pkg/gnap/authhandler/auth_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,34 +131,33 @@ func (h *AuthHandler) HandleAccessRequest( // nolint: funlen,gocyclo
return nil, fmt.Errorf("failed to determine permissions for access request: %w", err)
}

continueToken := gnap.AccessToken{
Value: uuid.New().String(),
}

s.ContinueToken = &api.ExpiringToken{AccessToken: continueToken}

s.NeedsConsent = permissions.NeedsConsent

// TODO: smarter access policy logic, to recognize if a token is being re-requested, and send that token instead of
// creating fresh access tokens every time.

if permissions.NeedsConsent.IsEmpty() && !permissions.Allowed.IsEmpty() {
// nothing needs consent, but something is allowed, so create tokens for all allowed, and return
var newTokens []gnap.AccessToken
newTokens, s = h.createTokens(permissions.Allowed.Tokens, s)
var resp *gnap.AuthResponse

err = h.sessionStore.Save(s)
resp, s, err = h.tokensGranted(permissions.Allowed.Tokens, s)
if err != nil {
return nil, err
}

resp := &gnap.AuthResponse{
AccessToken: newTokens,
err = h.sessionStore.Save(s)
if err != nil {
return nil, err
}

return resp, nil
}

continueToken := gnap.AccessToken{
Value: uuid.New().String(),
}

s.ContinueToken = &api.ExpiringToken{AccessToken: continueToken}

s.NeedsConsent = permissions.NeedsConsent

s.AllowedRequest = permissions.Allowed

// TODO: support selecting one of multiple interaction handlers
Expand Down Expand Up @@ -211,15 +210,21 @@ func (h *AuthHandler) HandleContinueRequest(

s.AddSubjectData(consent.SubjectData)

var newTokens, addedTokens []gnap.AccessToken
newTokens, s = h.createTokens(consent.Tokens, s)
var tokReqs []*api.ExpiringTokenRequest

tokReqs = append(tokReqs, consent.Tokens...)

// create fresh tokens for all requested tokens that were already permitted before this consent interaction
if s.AllowedRequest != nil {
addedTokens, s = h.createTokens(s.AllowedRequest.Tokens, s)
tokReqs = append(tokReqs, s.AllowedRequest.Tokens...)
}

newTokens = append(newTokens, addedTokens...)
var resp *gnap.AuthResponse

resp, s, err = h.tokensGranted(tokReqs, s)
if err != nil {
return nil, err
}

// clear request metadata, since these are now granted
s.AllowedRequest = nil
Expand All @@ -235,11 +240,40 @@ func (h *AuthHandler) HandleContinueRequest(
return nil, err
}

return resp, nil
}

func (h *AuthHandler) tokensGranted(
tokReqs []*api.ExpiringTokenRequest,
s *session.Session,
) (
*gnap.AuthResponse,
*session.Session,
error,
) {
var newTokens []gnap.AccessToken

newTokens, s = h.createTokens(tokReqs, s)

resp := &gnap.AuthResponse{
AccessToken: newTokens,
}

return resp, nil
subjectData, err := h.getSubjectData(newTokens, s)
if err != nil {
return nil, nil, err
}

if sub, ok := subjectData["sub"]; ok {
resp.Subject.SubIDs = []gnap.SubjectID{
{
Format: "opaque",
ID: sub,
},
}
}

return resp, s, nil
}

func (h *AuthHandler) createTokens(
Expand Down Expand Up @@ -279,8 +313,34 @@ func (h *AuthHandler) createTokens(
return newTokens, clientSession
}

func (h *AuthHandler) getSubjectData(
tokens []gnap.AccessToken,
clientSession *session.Session,
) (map[string]string, error) {
mergedAccess := []gnap.TokenAccess{}

for _, token := range tokens {
mergedAccess = append(mergedAccess, token.Access...)
}

subjectKeys, err := h.accessPolicy.AllowedSubjectKeys(mergedAccess)
if err != nil {
return nil, fmt.Errorf("error fetching subject-data keys: %w", err)
}

subjectData := map[string]string{}

for k := range subjectKeys {
if v, ok := clientSession.SubjectData[k]; ok {
subjectData[k] = v
}
}

return subjectData, nil
}

// HandleIntrospection handles GNAP resource-server requests for access token introspection.
func (h *AuthHandler) HandleIntrospection( // nolint:gocyclo,funlen
func (h *AuthHandler) HandleIntrospection( // nolint:gocyclo
req *gnap.IntrospectRequest,
reqVerifier api.Verifier,
) (*gnap.IntrospectResponse, error) {
Expand Down Expand Up @@ -325,23 +385,17 @@ func (h *AuthHandler) HandleIntrospection( // nolint:gocyclo,funlen
return &gnap.IntrospectResponse{Active: false}, nil
}

subjectKeys, err := h.accessPolicy.AllowedSubjectKeys(clientToken.Access)
subjectData, err := h.getSubjectData([]gnap.AccessToken{clientToken.AccessToken}, clientSession)
if err != nil {
err = fmt.Errorf("error fetching subject-data keys for requested token: %w", err)
return nil, fmt.Errorf("get subject data: %w", err)
}

resp := &gnap.IntrospectResponse{
Active: true,
Access: clientToken.Access,
Key: clientSession.ClientKey,
Flags: clientToken.Flags,
SubjectData: map[string]string{},
}

for k := range subjectKeys {
if v, ok := clientSession.SubjectData[k]; ok {
resp.SubjectData[k] = v
}
SubjectData: subjectData,
}

return resp, err
Expand Down
46 changes: 39 additions & 7 deletions pkg/gnap/authhandler/auth_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/trustbloc/auth/pkg/gnap/accesspolicy"
"github.com/trustbloc/auth/pkg/gnap/api"
"github.com/trustbloc/auth/pkg/gnap/session"
"github.com/trustbloc/auth/pkg/internal/common/mockinteract"
"github.com/trustbloc/auth/pkg/internal/common/mockstorage"
"github.com/trustbloc/auth/pkg/internal/common/mockverifier"
Expand Down Expand Up @@ -389,6 +390,8 @@ func TestAuthHandler_HandleContinueRequest(t *testing.T) {
h, err := New(config(t))
require.NoError(t, err)

subID := "JohnDoe12341234"

h.loginConsent = &mockinteract.InteractHandler{
QueryVal: &api.ConsentResult{
Tokens: []*api.ExpiringTokenRequest{
Expand All @@ -397,13 +400,17 @@ func TestAuthHandler_HandleContinueRequest(t *testing.T) {
Access: []gnap.TokenAccess{
{
IsReference: true,
Ref: "foo",
Ref: "client-id",
},
},
Label: "foo",
},
},
},

SubjectData: map[string]string{
"sub": subID,
},
},
}

Expand All @@ -421,7 +428,7 @@ func TestAuthHandler_HandleContinueRequest(t *testing.T) {
Access: []gnap.TokenAccess{
{
IsReference: true,
Ref: "bar",
Ref: "other-access",
},
},
Label: "bar",
Expand All @@ -439,6 +446,9 @@ func TestAuthHandler_HandleContinueRequest(t *testing.T) {
// TODO: validate that one token is foo, one token is bar, either order
require.Equal(t, "foo", resp.AccessToken[0].Label)
require.Equal(t, "bar", resp.AccessToken[1].Label)

require.Len(t, resp.Subject.SubIDs, 1)
require.Equal(t, subID, resp.Subject.SubIDs[0].ID)
})
}

Expand Down Expand Up @@ -618,8 +628,8 @@ func TestAuthHandler_HandleIntrospection(t *testing.T) {

clientSession.Tokens = append(clientSession.Tokens, &api.ExpiringToken{AccessToken: *token})
clientSession.AddSubjectData(map[string]string{
clientIDKey: clientIDVal,
"secret": "blah blah",
"sub": clientIDVal,
"secret": "blah blah",
})

require.NoError(t, h.sessionStore.Save(clientSession))
Expand All @@ -641,13 +651,35 @@ func TestAuthHandler_HandleIntrospection(t *testing.T) {
Access: token.Access,
Key: clientVerKey,
SubjectData: map[string]string{
clientIDKey: clientIDVal,
"sub": clientIDVal,
},
}
require.Equal(t, expectedResp, resp)
})
}

func TestAuthHandler_tokensGranted(t *testing.T) {
t.Run("failure", func(t *testing.T) {
h, err := New(config(t))
require.NoError(t, err)

_, _, err = h.tokensGranted([]*api.ExpiringTokenRequest{
{
TokenRequest: gnap.TokenRequest{
Access: []gnap.TokenAccess{
{
IsReference: true,
Ref: "not-found",
},
},
},
},
}, &session.Session{})
require.Error(t, err)
require.Contains(t, err.Error(), "fetching subject-data keys")
})
}

func config(t *testing.T) *Config {
t.Helper()

Expand Down Expand Up @@ -688,8 +720,8 @@ const (
"permission": "NeedsConsent",
"access": {
"type": "trustbloc.xyz/auth/type/client-id",
"subject-keys": ["client-id"],
"userid-key": "client-id"
"subject-keys": ["sub"],
"userid-key": "sub"
}
}, {
"reference": "other-access",
Expand Down
6 changes: 3 additions & 3 deletions test/bdd/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693
github.com/tidwall/gjson v1.14.1
github.com/trustbloc/auth v0.0.0
github.com/trustbloc/auth/spi/gnap v0.0.0-20220518152301-fe6ea3ada1af
github.com/trustbloc/auth/spi/gnap v0.0.0-20220623204824-c6be06c93136
github.com/trustbloc/edge-core v0.1.8
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
)
Expand Down Expand Up @@ -75,7 +75,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.7.1 // indirect
github.com/stretchr/testify v1.7.2 // indirect
github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
Expand All @@ -91,7 +91,7 @@ require (
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.0.3 // indirect
)

Expand Down
Loading

0 comments on commit 1b9a649

Please sign in to comment.