Skip to main content
Kratos supports multiple credential types for authenticating identities. This guide covers how to manage credentials through the Admin API and CLI.

Credential types

Kratos supports the following credential types:
TypeDescriptionAAL
passwordUsername/password authenticationAAL1
oidcOAuth 2.0 / OpenID Connect social sign-inAAL1
samlSAML 2.0 single sign-onAAL1
webauthnWebAuthn/FIDO2 security keysAAL1/AAL2
passkeyPasswordless WebAuthnAAL1
totpTime-based one-time passwordsAAL2
lookup_secretBackup recovery codesAAL2
codePasswordless email/SMS codesAAL1

Credential structure

Each credential contains:
identity/credentials.go
type Credentials struct {
    ID          uuid.UUID
    Type        CredentialsType
    Identifiers []string
    Config      sqlxx.JSONRawMessage
    Version     int
    IdentityID  uuid.UUID
    CreatedAt   time.Time
    UpdatedAt   time.Time
}

Identifiers

Identifiers are unique values used to look up an identity:
  • Password/Code: Email addresses or usernames from traits
  • OIDC/SAML: Provider-specific subject identifiers (e.g., google:123456)
  • WebAuthn: Credential IDs

Managing password credentials

Update password via Admin API

curl -X PUT "https://kratos-admin/admin/identities/{id}" \
  -H "Content-Type: application/json" \
  -d '{
    "schema_id": "default",
    "traits": {
      "email": "[email protected]"
    },
    "credentials": {
      "password": {
        "config": {
          "password": "new-secure-password"
        }
      }
    }
  }'

Password credential config

identity/credentials_password.go
type CredentialsPassword struct {
    HashedPassword           string `json:"hashed_password"`
    UsePasswordMigrationHook bool   `json:"use_password_migration_hook,omitempty"`
}
Passwords are hashed using bcrypt. The Admin API accepts both plaintext (which will be hashed) and pre-hashed passwords in PHC format.

Managing OIDC credentials

OIDC credential structure

identity/credentials_oidc.go
type CredentialsOIDC struct {
    Providers []CredentialsOIDCProvider `json:"providers"`
}

type CredentialsOIDCProvider struct {
    Subject             string `json:"subject"`
    Provider            string `json:"provider"`
    InitialIDToken      string `json:"initial_id_token"`
    InitialAccessToken  string `json:"initial_access_token"`
    InitialRefreshToken string `json:"initial_refresh_token"`
    Organization        string `json:"organization,omitempty"`
    UseAutoLink         bool   `json:"use_auto_link,omitzero"`
}

Import OIDC connection

POST /admin/identities
{
  "schema_id": "default",
  "traits": {
    "email": "[email protected]"
  },
  "credentials": {
    "oidc": {
      "config": {
        "providers": [
          {
            "subject": "google-user-id-12345",
            "provider": "google"
          }
        ]
      }
    }
  }
}
OIDC identifiers use the format {provider}:{subject}. Each provider-subject combination must be unique across all identities.
The use_auto_link flag allows users to sign in with an OIDC provider without requiring the subject to be set first:
{
  "subject": "temp-placeholder",
  "provider": "google",
  "use_auto_link": true
}

Managing multi-factor credentials

TOTP (Authenticator apps)

TOTP credentials are typically added by users through self-service flows, but can be managed via the Admin API:
Delete TOTP credential
curl -X DELETE "https://kratos-admin/admin/identities/{id}/credentials/totp"

Lookup secrets (Recovery codes)

Backup recovery codes for MFA:
Delete lookup secrets
curl -X DELETE "https://kratos-admin/admin/identities/{id}/credentials/lookup_secret"

WebAuthn credentials

Managing WebAuthn credentials:
1

Delete WebAuthn credential

curl -X DELETE \
  "https://kratos-admin/admin/identities/{id}/credentials/webauthn"
This removes all non-passwordless WebAuthn credentials (security keys used for second factor).
2

Preserve passwordless credentials

The delete operation automatically preserves passwordless WebAuthn credentials (passkeys), as they serve as first-factor authentication.

Deleting credentials

Delete specific credential type

DELETE /admin/identities/{id}/credentials/{type}
Path parameters:
  • id: Identity UUID
  • type: Credential type (password, oidc, saml, totp, lookup_secret, webauthn)
Query parameters:
  • identifier: Required for OIDC/SAML to specify which provider to remove

Delete OIDC provider

When an identity has multiple OIDC providers, specify which one to remove:
curl -X DELETE \
  "https://kratos-admin/admin/identities/{id}/credentials/oidc?identifier=google:12345"

Restrictions

  • Cannot delete the last first-factor credential (users must have at least one way to authenticate)
  • Cannot delete passkey or code credentials through this API
  • Deleting the current session’s credential is prevented

Credential validation

Kratos performs validation when updating credentials:
1

Schema validation

Traits are validated against the identity schema to ensure credentials have proper identifiers.
2

Identifier uniqueness

Credential identifiers must be unique across all identities in the same project.
3

Hash format validation

Imported password hashes must be in a valid format (bcrypt, argon2, pbkdf2, or scrypt).
4

AAL calculation

The available Authenticator Assurance Level is calculated based on configured credentials.

Credential versioning

Each credential has a version field that tracks schema changes:
func (i *Identity) UpsertCredentialsConfig(
    t CredentialsType,
    conf []byte,
    version int,
    opt ...CredentialsOptions,
) {
    c.Type = t
    c.Config = conf
    c.Version = version
    i.SetCredentials(t, *c)
}
Version numbers allow Kratos to handle credential config migrations when the internal structure changes.

Available AAL

The available_aal field indicates the highest AAL the identity can achieve:
identity/identity.go
func (i *Identity) SetAvailableAAL(ctx context.Context, m *Manager) error {
    if c, err := m.CountActiveMultiFactorCredentials(ctx, i); err != nil {
        return err
    } else if c > 0 {
        i.InternalAvailableAAL = NewNullableAuthenticatorAssuranceLevel(AuthenticatorAssuranceLevel2)
        return nil
    }

    if c, err := m.CountActiveFirstFactorCredentials(ctx, i); err != nil {
        return err
    } else if c > 0 {
        i.InternalAvailableAAL = NewNullableAuthenticatorAssuranceLevel(AuthenticatorAssuranceLevel1)
        return nil
    }

    i.InternalAvailableAAL = NewNullableAuthenticatorAssuranceLevel(NoAuthenticatorAssuranceLevel)
    return nil
}

Examples

Create identity with multiple credential types

POST /admin/identities
{
  "schema_id": "default",
  "traits": {
    "email": "[email protected]",
    "username": "johndoe"
  },
  "credentials": {
    "password": {
      "config": {
        "password": "secure-password-123"
      }
    },
    "oidc": {
      "config": {
        "providers": [
          {
            "subject": "google-12345",
            "provider": "google"
          },
          {
            "subject": "github-67890",
            "provider": "github"
          }
        ]
      }
    }
  }
}

Check credential configuration

curl -X GET \
  "https://kratos-admin/admin/identities/{id}?include_credential=oidc&include_credential=password"
Response includes full credential details:
{
  "id": "...",
  "credentials": {
    "password": {
      "type": "password",
      "identifiers": ["[email protected]", "johndoe"],
      "config": {}
    },
    "oidc": {
      "type": "oidc",
      "identifiers": ["google:12345", "github:67890"],
      "config": {
        "providers": [...]
      }
    }
  }
}

Build docs developers (and LLMs) love