<@U04UQ68083H> in ory kratos self-hosted we'd like...
# ory-copilot
a
@chilly-king-10285 in ory kratos self-hosted we'd like to offer the ability to use either: 1. email + password / code / passkey 2. phone + code / passkey How do we setup the schema to have either the email or phone as a requirement and not both? Also, is it possible to later add a the other identifier to an account so that if someone originally was registered with just phone number that their email could be added as an identifier so the user could now login in with either identifier and the single password?
b
A message from kapa.ai
To set up the schema in Ory Kratos to allow either email or phone as a requirement (but not both) and to enable the login methods you described, you can use a custom identity schema. Here's how you can achieve this: 1. Create a custom identity schema that allows either email or phone:
Copy code
json
{
  "$id": "<https://example.com/custom.schema.json>",
  "$schema": "<http://json-schema.org/draft-07/schema#>",
  "title": "Person",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string",
          "format": "email",
          "title": "E-Mail",
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "password": {
                "identifier": true
              },
              "code": {
                "identifier": true,
                "via": "email"
              },
              "passkey": {
                "display_name": true
              }
            },
            "recovery": {
              "via": "email"
            },
            "verification": {
              "via": "email"
            }
          }
        },
        "phone": {
          "type": "string",
          "format": "tel",
          "title": "Phone",
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "code": {
                "identifier": true,
                "via": "sms"
              },
              "passkey": {
                "display_name": true
              }
            },
            "recovery": {
              "via": "sms"
            },
            "verification": {
              "via": "sms"
            }
          }
        }
      },
      "anyOf": [
        { "required": ["email"] },
        { "required": ["phone"] }
      ],
      "additionalProperties": false
    }
  }
}
This schema uses the
anyOf
keyword to require either email or phone, but not necessarily both. It also sets up the appropriate credentials for each identifier as per your requirements. To implement this schema, you need to save it as a JSON file and configure Kratos to use it. You can find more information on how to do this in the [Ory Kratos Identity Schema documentation](https://www.ory.sh/docs/kratos/manage-identities/identity-schema). Regarding your second question about adding another identifier later: Yes, it is possible to add another identifier to an account after initial registration. However, the exact implementation depends on your specific setup and might require custom development. To allow users to add another identifier (e.g., email for a user who initially registered with a phone number), you would need to: 1. Implement a settings or profile update flow in your application. 2. Use the Ory Kratos API to update the user's identity with the new identifier. 3. Ensure that the new identifier is properly verified before allowing its use for authentication.
To set up the schema in Ory Kratos to allow either email or phone as a requirement (but not both) and to enable the login methods you described, you can use a custom identity schema. Here's how you can achieve this: 1. Create a custom identity schema that allows either email or phone:
Copy code
json {   "$id": "<https://example.com/custom.schema.json>",   "$schema": "<http://json-schema.org/draft-07/schema#>",   "title": "Person",   "type": "object",   "properties": {     "traits": {       "type": "object",       "properties": {         "email": {           "type": "string",           "format": "email",           "title": "E-Mail",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "password": {                 "identifier": true               },               "code": {                 "identifier": true,                 "via": "email"               },               "passkey": {                 "display_name": true               }             },             "recovery": {               "via": "email"             },             "verification": {               "via": "email"             }           }         },         "phone": {           "type": "string",           "format": "tel",           "title": "Phone",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "code": {                 "identifier": true,                 "via": "sms"               },               "passkey": {                 "display_name": true               }             },             "recovery": {               "via": "sms"             },             "verification": {               "via": "sms"             }           }         }       },       "anyOf": [         { "required": ["email"] },         { "required": ["phone"] }       ],       "additionalProperties": false     }   } }
This schema uses the
anyOf
keyword to require either email or phone, but not necessarily both. It also sets up the appropriate credentials for each identifier as per your requirements. To implement this schema, you need to save it as a JSON file and configure Kratos to use it. You can find more information on how to do this in the [Ory Kratos Identity Schema documentation](https://www.ory.sh/docs/kratos/manage-identities/identity-schema). Regarding your second question about adding another identifier later: Yes, it is possible to add another identifier to an account after initial registration. However, the exact implementation depends on your specific setup and might require custom development. To allow users to add another identifier (e.g., email for a user who initially registered with a phone number), you would need to: 1. Implement a settings or profile update flow in your application. 2. Use the Ory Kratos API to update the user's identity with the new identifier. 3. Ensure that the new identifier is properly verified before allowing its use for authentication. The Ory Kratos documentation doesn't provide a specific example for this scenario, but you can refer to the [Identity Schema Extensions](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema#identity-schema-extensions) section for guidance on how to structure your schema to support multiple identifiers. Keep in mind that implementing this feature securely requires careful consideration of verification processes and potential security implications. It's recommended to thoroughly test your implementation and consider seeking advice from security experts if you're unsure about any aspects of the implementation.
a
@chilly-king-10285 I'm afraid
format: tel
or
format: email
won't let me save it as empty string (even if I omit the property)
b
A message from kapa.ai
You're right to be concerned about the
format: tel
and
format: email
validations potentially causing issues with empty strings. The JSON Schema validation for these formats indeed doesn't allow empty strings by default. However, we can modify the schema to accommodate this requirement. Here's how you can adjust your schema to allow either email or phone to be optional while still maintaining the format validation when a value is provided:
Copy code
json
{
  "$id": "<https://example.com/custom.schema.json>",
  "$schema": "<http://json-schema.org/draft-07/schema#>",
  "title": "Person",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "type": ["string", "null"],
          "format": "email",
          "title": "E-Mail",
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "password": {
                "identifier": true
              },
              "code": {
                "identifier": true,
                "via": "email"
              },
              "passkey": {
                "display_name": true
              }
            },
            "recovery": {
              "via": "email"
            },
            "verification": {
              "via": "email"
            }
          }
        },
        "phone": {
          "type": ["string", "null"],
          "format": "tel",
          "title": "Phone",
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "code": {
                "identifier": true,
                "via": "sms"
              },
              "passkey": {
                "display_name": true
              }
            },
            "recovery": {
              "via": "sms"
            },
            "verification": {
              "via": "sms"
            }
          }
        }
      },
      "anyOf": [
        { "required": ["email"], "properties": { "email": { "type": "string", "minLength": 1 } } },
        { "required": ["phone"], "properties": { "phone": { "type": "string", "minLength": 1 } } }
      ],
      "additionalProperties": false
    }
  }
}
In this modified schema: 1. We've changed the
type
for both
email
and
phone
to
["string", "null"]
. This allows these fields to be either a string or null, effectively making them optional. 2. In the
anyOf
section, we've added an additional constraint
"minLength": 1
for each property. This ensures that when the property is present, it must contain at least one character. This approach allows you to: - Omit the email or phone property entirely - Set the value to null - Provide a non-empty string value that adheres to the respective format When a value is provided, it will still be validated against the
email
or
tel
format as appropriate.
You're right to be concerned about the
format: tel
and
format: email
validations potentially causing issues with empty strings. The JSON Schema validation for these formats indeed doesn't allow empty strings by default. However, we can modify the schema to accommodate this requirement. Here's how you can adjust your schema to allow either email or phone to be optional while still maintaining the format validation when a value is provided:
Copy code
json {   "$id": "<https://example.com/custom.schema.json>",   "$schema": "<http://json-schema.org/draft-07/schema#>",   "title": "Person",   "type": "object",   "properties": {     "traits": {       "type": "object",       "properties": {         "email": {           "type": ["string", "null"],           "format": "email",           "title": "E-Mail",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "password": {                 "identifier": true               },               "code": {                 "identifier": true,                 "via": "email"               },               "passkey": {                 "display_name": true               }             },             "recovery": {               "via": "email"             },             "verification": {               "via": "email"             }           }         },         "phone": {           "type": ["string", "null"],           "format": "tel",           "title": "Phone",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "code": {                 "identifier": true,                 "via": "sms"               },               "passkey": {                 "display_name": true               }             },             "recovery": {               "via": "sms"             },             "verification": {               "via": "sms"             }           }         }       },       "anyOf": [         { "required": ["email"], "properties": { "email": { "type": "string", "minLength": 1 } } },         { "required": ["phone"], "properties": { "phone": { "type": "string", "minLength": 1 } } }       ],       "additionalProperties": false     }   } }
In this modified schema: 1. We've changed the
type
for both
email
and
phone
to
["string", "null"]
. This allows these fields to be either a string or null, effectively making them optional. 2. In the
anyOf
section, we've added an additional constraint
"minLength": 1
for each property. This ensures that when the property is present, it must contain at least one character. This approach allows you to: - Omit the email or phone property entirely - Set the value to null - Provide a non-empty string value that adheres to the respective format When a value is provided, it will still be validated against the
email
or
tel
format as appropriate. Remember, while this schema allows for more flexibility, you'll need to ensure that your application logic handles these cases appropriately, especially when dealing with authentication and verification flows. For more information on customizing identity schemas in Ory Kratos, you can refer to the [Ory Kratos documentation on customizing identity schemas](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema).
a
@chilly-king-10285 The strange thing here with passkey on the phone property. The both schemas you provided I got
no identifier found
error message on the registration screen. But if I delete passkey from the phone property, it works
b
A message from kapa.ai
I understand your confusion regarding the passkey configuration on the phone property. Let's investigate this issue based on the information provided in the knowledge sources. The error message "no identifier found" typically occurs when the identity schema doesn't properly define login identifiers. In this case, it seems that the presence of the passkey configuration on the phone property is causing unexpected behavior. Based on the [Ory Kratos documentation on identity schema extensions](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema#identity-schema-extensions), the
passkey
configuration should be used with the
display_name
property, which is typically associated with a username or email rather than a phone number. Let's modify the schema to remove the passkey configuration from the phone property and keep it only for the email:
Copy code
json
{
  "$id": "<https://example.com/custom.schema.json>",
  "$schema": "<http://json-schema.org/draft-07/schema#>",
  "title": "Person",
  "type": "object",
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        "email": {
          "type": ["string", "null"],
          "format": "email",
          "title": "E-Mail",
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "password": {
                "identifier": true
              },
              "code": {
                "identifier": true,
                "via": "email"
              },
              "passkey": {
                "display_name": true
              }
            },
            "recovery": {
              "via": "email"
            },
            "verification": {
              "via": "email"
            }
          }
        },
        "phone": {
          "type": ["string", "null"],
          "format": "tel",
          "title": "Phone",
          "<http://ory.sh/kratos|ory.sh/kratos>": {
            "credentials": {
              "code": {
                "identifier": true,
                "via": "sms"
              }
            },
            "recovery": {
              "via": "sms"
            },
            "verification": {
              "via": "sms"
            }
          }
        }
      },
      "anyOf": [
        { "required": ["email"], "properties": { "email": { "type": "string", "minLength": 1 } } },
        { "required": ["phone"], "properties": { "phone": { "type": "string", "minLength": 1 } } }
      ],
      "additionalProperties": false
    }
  }
}
This modification should resolve the "no identifier found" error you encountered. The passkey is now only associated with the email property, which is more in line with typical passkey usage. If you still encounter issues or need to use passkeys with phone numbers, you might need to consult the Ory team directly or check for any recent updates in the documentation, as the behavior you're experiencing might be due to a specific implementation detail or a potential bug.
I understand your confusion regarding the passkey configuration on the phone property. Let's investigate this issue based on the information provided in the knowledge sources. The error message "no identifier found" typically occurs when the identity schema doesn't properly define login identifiers. In this case, it seems that the presence of the passkey configuration on the phone property is causing unexpected behavior. Based on the [Ory Kratos documentation on identity schema extensions](https://www.ory.sh/docs/kratos/manage-identities/customize-identity-schema#identity-schema-extensions), the
passkey
configuration should be used with the
display_name
property, which is typically associated with a username or email rather than a phone number. Let's modify the schema to remove the passkey configuration from the phone property and keep it only for the email:
Copy code
json {   "$id": "<https://example.com/custom.schema.json>",   "$schema": "<http://json-schema.org/draft-07/schema#>",   "title": "Person",   "type": "object",   "properties": {     "traits": {       "type": "object",       "properties": {         "email": {           "type": ["string", "null"],           "format": "email",           "title": "E-Mail",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "password": {                 "identifier": true               },               "code": {                 "identifier": true,                 "via": "email"               },               "passkey": {                 "display_name": true               }             },             "recovery": {               "via": "email"             },             "verification": {               "via": "email"             }           }         },         "phone": {           "type": ["string", "null"],           "format": "tel",           "title": "Phone",           "<http://ory.sh/kratos|ory.sh/kratos>": {             "credentials": {               "code": {                 "identifier": true,                 "via": "sms"               }             },             "recovery": {               "via": "sms"             },             "verification": {               "via": "sms"             }           }         }       },       "anyOf": [         { "required": ["email"], "properties": { "email": { "type": "string", "minLength": 1 } } },         { "required": ["phone"], "properties": { "phone": { "type": "string", "minLength": 1 } } }       ],       "additionalProperties": false     }   } }
This modification should resolve the "no identifier found" error you encountered. The passkey is now only associated with the email property, which is more in line with typical passkey usage. If you still encounter issues or need to use passkeys with phone numbers, you might need to consult the Ory team directly or check for any recent updates in the documentation, as the behavior you're experiencing might be due to a specific implementation detail or a potential bug. For further assistance, you may want to check the [Ory Kratos GitHub discussions](https://github.com/ory/kratos/discussions) or open an issue if you believe this is unexpected behavior.