diff --git a/cmd/identities/get.go b/cmd/identities/get.go index 148bbdcb49a..d4f8c8faf40 100644 --- a/cmd/identities/get.go +++ b/cmd/identities/get.go @@ -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" @@ -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 ", 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. @@ -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 @@ -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 } diff --git a/cmd/identities/get_test.go b/cmd/identities/get_test.go index 6369517153d..911da181e28 100644 --- a/cmd/identities/get_test.go +++ b/cmd/identities/get_test.go @@ -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" @@ -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) + }) }