Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cmd): add oidc credential include #2017

Merged
merged 4 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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).
zepatrik marked this conversation as resolved.
Show resolved Hide resolved
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)
})
}