Skip to content

Commit

Permalink
feat(cmd): add OIDC credential include (ory#2017)
Browse files Browse the repository at this point in the history
With this change, the `kratos identities get` CLI can additionally fetch OIDC credentials.

Co-authored-by: Patrik <zepatrik@users.noreply.github.com>
  • Loading branch information
alexandrebrg and zepatrik committed Dec 6, 2021
1 parent 906c975 commit fb0f74b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 2 deletions.
31 changes: 29 additions & 2 deletions cmd/identities/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
kratos "github.com/ory/kratos-client-go"
"github.com/ory/kratos/x"
"github.com/ory/x/cmdx"
"github.com/ory/x/stringsx"

"github.com/ory/kratos/internal/clihelpers"

Expand All @@ -14,8 +15,16 @@ import (
"github.com/ory/kratos/cmd/cliclient"
)

const (
FlagIncludeCreds = "include-credentials"
)

func NewGetCmd() *cobra.Command {
return &cobra.Command{
var (
includeCreds []string
)

cmd := &cobra.Command{
Use: "get <id-0 [id-1 ...]>",
Short: "Get one or more identities by ID",
Long: fmt.Sprintf(`This command gets all the details about an identity. To get an identity by some selector, e.g. the recovery email address, use the list command in combination with jq.
Expand All @@ -29,10 +38,23 @@ func NewGetCmd() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
c := cliclient.NewClient(cmd)

// we check includeCreds argument is valid
for _, opt := range includeCreds {
e := stringsx.SwitchExact(opt)
if !e.AddCase("oidc") {
cmd.PrintErrln(`You have to put a valid value of credentials type to be included, try --help for details.`)
return cmdx.FailSilently(cmd)
}
}

identities := make([]kratos.Identity, 0, len(args))
failed := make(map[string]error)
for _, id := range args {
identity, _, err := c.V0alpha2Api.AdminGetIdentity(cmd.Context(), id).Execute()
identity, _, err := c.V0alpha2Api.
AdminGetIdentity(cmd.Context(), id).
IncludeCredential(includeCreds).
Execute()

if x.SDKError(err) != nil {
failed[id] = err
continue
Expand All @@ -54,4 +76,9 @@ func NewGetCmd() *cobra.Command {
return nil
},
}

flags := cmd.Flags()
// include credential flag to add third party tokens in returned data
flags.StringArrayVarP(&includeCreds, FlagIncludeCreds, "i", []string{}, `Include third party tokens (only "oidc" supported) `)
return cmd
}
53 changes: 53 additions & 0 deletions cmd/identities/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package identities_test

import (
"context"
"encoding/hex"
"encoding/json"
"testing"

"github.com/ory/kratos/cmd/identities"
"github.com/ory/kratos/selfservice/strategy/oidc"

"github.com/ory/x/assertx"

Expand Down Expand Up @@ -50,4 +52,55 @@ func TestGetCmd(t *testing.T) {

assert.Contains(t, stdErr, "404 Not Found", stdErr)
})

t.Run("case=gets a single identity with oidc credentials", func(t *testing.T) {
applyCredentials := func(identifier, accessToken, refreshToken, idToken string, encrypt bool) identity.Credentials {
toJson := func(c oidc.CredentialsConfig) []byte {
out, err := json.Marshal(&c)
require.NoError(t, err)
return out
}
transform := func(token string) string {
if !encrypt {
return token
}
return hex.EncodeToString([]byte(token))
}
return identity.Credentials{
Type: identity.CredentialsTypeOIDC,
Identifiers: []string{"bar:" + identifier},
Config: toJson(oidc.CredentialsConfig{Providers: []oidc.ProviderCredentialsConfig{
{
Subject: "foo",
Provider: "bar",
InitialAccessToken: transform(accessToken + "0"),
InitialRefreshToken: transform(refreshToken + "0"),
InitialIDToken: transform(idToken + "0"),
},
{
Subject: "baz",
Provider: "zab",
InitialAccessToken: transform(accessToken + "1"),
InitialRefreshToken: transform(refreshToken + "1"),
InitialIDToken: transform(idToken + "1"),
},
}}),
}
}
i := identity.NewIdentity(config.DefaultIdentityTraitsSchemaID)
i.SetCredentials(identity.CredentialsTypeOIDC, applyCredentials("uniqueIdentifier", "accessBar", "refreshBar", "idBar", true))
// duplicate identity with decrypted tokens
di := i.CopyWithoutCredentials()
di.SetCredentials(identity.CredentialsTypeOIDC, applyCredentials("uniqueIdentifier", "accessBar", "refreshBar", "idBar", false))

require.NoError(t, c.Flags().Set(identities.FlagIncludeCreds, "oidc"))
require.NoError(t, reg.Persister().CreateIdentity(context.Background(), i))

stdOut := execNoErr(t, c, i.ID.String())
ij, err := json.Marshal(identity.WithCredentialsInJSON(*di))
require.NoError(t, err)

ii := []string{"schema_url", "state_changed_at", "created_at", "updated_at", "credentials.oidc.created_at", "credentials.oidc.updated_at"}
assertx.EqualAsJSONExcept(t, json.RawMessage(ij), json.RawMessage(stdOut), ii)
})
}

0 comments on commit fb0f74b

Please sign in to comment.