Stash repo with source to test: https://stash.forgerock.org/users/hanns.nolan/repos/idm6-selfservice-examples/browse
Prerequisites
- SMTP port 1125 (running mailcatcher in docker)
- Grafana/Prometheus/nodeexporter running on default ports in docker (if you want to test this as well!)
- IDM can be startet with ./startup.sh -p projectdir -w workingdir
Overview of the functions in IDM6
User Self Registration
- Flexible data schema
- Social registration
- Options (can be switched on requirements)
- Google ReCAPTCHA
- Email validation
- Security Questions
- Terms & Conditions (including Versioning/audit in internal objects)
- Privacy & Consent (including consent trail in user managed objects)
- Available also per REST API (see example below)
- Multiple self-registration endpoints possible (see note from Jake)
Password Rest Self Service
- Options (can be switched on requirements)
- Google ReCAPTCHA
- User Query Form
- Email Validation
- Security Questions
- Password reset form (pwd attribute)
Forgotten Username Retrieval
- Options (can be switched on requirements)
- Google ReCAPTCHA
- User Query Form
- Email Username
- Display Username
Progressive Profile Compilation
- free form definition with user display Options
- Display conditions
- Basic Conditions on login counts/property value/time since reg/profile completion
- Advanced Conditions query filter/script
- Attributes property not required/required
Terms & Conditions
- Versioning of T&C with language support
- Require acceptance for new and existing users
Docs
Self-Service REST API Reference
user registration flow
Rest call flow
1. user registration with payload
curl -X POST \
'https://localhost:8443/openidm/selfservice/registration?_action=submitRequirements' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-H 'X-OpenIDM-Password: anonymous' \
-H 'X-OpenIDM-Username: anonymous' \
-d '{
"input": {
"user": {
"userName": "hnolan",
"givenName": "Hanns",
"sn": "Nolan",
"mail": "hanns.nolan@forgerock.com",
"password": "Passw0rd",
"preferences": {
"updates": true,
"marketing": false
}
},
"accept": "true",
"kba": [
{
"answer": "color",
"questionId": "1"
}
]
}
}'
Respond:
{
"type": "emailValidation",
"tag": "validateCode",
"requirements": {
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Verify emailed code",
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"description": "Enter code emailed",
"type": "string"
}
}
},
"token": "eyJ0eXAiOiJKV1QiLCJjdHkiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.ZXlKMGVYQWlPaUpLVjFRaUxDSmxibU1pT2lKQk1USTRRMEpETFVoVE1qVTJJaXdpWVd4bklqb2lVbE5CTVY4MUluMC5OSm8zTTYyNTdoazJPUDNIYmRUMzNtT0VOc1p0a0xmaHAwazBZc2dZVEdSUVFrZzFQYjZYUEdITlBQdE1sU1FZTGxoQkEyZkJ0V3Y3WEIwUzhCTWlQMHFoN3NBT1p6U0JSSGgtczFEeWhENE5oSU45NzU4dmNyeFp2bjFMTUxHYi1EenFnR1FKRXFvcHR6SU1FcGFWTElvLTdJR1BxMjd0bFRGVDBWQTZsMi1mSVZTaVptT1pVZkNKM1Z6c1kzWk9VczcwLWlNdDZLcWZCZF8zOGVUV1RzQ0ZNZGRrT3dsNmRpOUlJSXRLTmt4RDFzaDZPSUthbDVPVFc1RFY5LXhDRUJxYVhrUFMwWV9JTGpFMFdsWDdPaWxFVm0xRG5CeUp1aDBfZkQxd1hERHExYWZJTVhNSWdTYTVNaEpGNnNtMFRiblJnWUo0NkhZczhScmRkZ1REWkEuYkxEdDZjb0JKWERScXJTWFJCemx0dy5QS2c3NGlhU1RQYnJfOXR2Y3BYTWoyVXMwUTJjR0JseW41X252NnFYYVpTb3hPOGV2aGkyLTZiT25wRXBsenAzQUY0MkZ1U0NYdHlYSmE2cmpJMjZIUXRwYzJMZGh6cGx0NGxvUXlfTmgxdFJWcTJuaWc2bDBjNEdiYVpsLVU5cVVCYkUxT09ac3dKbzhzNzlzSC0xMTlxZnVWZWxMUHNsVDhaTDcwZHhMNTdZal8wMlRUeUlNU3ZQT19uamxUdWFSUlJ0NDBYVHktX0FYTFphTzJkdXhaSWUyX1pWRDFxdGdKQ2ZOTTlKX1FZdU1MdklCRHZxSkZjSWxJbDVtcU5lSWpaZEVlOHp2c0F4VmFqcVhZNWtaZVdhVUVpamctZmZPT3E1ZV91eEZuV3ZYY2F3ZWRRZFFpVTBGcXJwRXpqcFY4R0JwdkUtQWd4Um5hSnl6Ry1wcXlKZnhYekp0ZzZlUkZaejVVUDVnNHZMTmhNWWN1Uko3WW1OYk1kRlB5RldwZlZ5Mmx2cWxvTTBaS0pKWVFLWU9Xc1hQR2x6UzFxSEFBTF9MWmFXbTVJQnozbmtVa2I3NHdLc18zWWlDZlJqREVMZVNIYlNENEdkR0h3cHlFMkFjNjVFdXpJQ1hNQVliRmRldXB2T3BFZHo3dTZTcWZqRkhCSC1BakRRdm5iellqY25Gdk81NmZDeHNfQTdwZzJWZXJEOFcyNWJfVC1MZHFXeVA3X09ZM2pQY3ZzdVd5aUlkVkRCOXlWWFg5TTAxRElFeWRzZkF0SjUzUElOYjZldUk0cnRnZWIwRXhVUTFqMWw1NkFUVS1iUkwzTU1WNWE5RVlCOEJsa1hoQWgzaWNiLTNSNVgyUU5qdzF6Z1lteFpIVFhLY1VabUxQNW1UblFkNHZRVGFvb2h1T2NxN3FvOGZBLUxtc2YwcU82NEM2OGNJb3FfUXFvck1WSFpPaHQ2ZXAyakxyaFlRbFVTOHNuVkw4dVgxQlVhNGFBRmY2by0xdjBJMkJ1QUhJYzhUU1hTRTdaaXp1bWhLcmtqa1R2M1h3UnItdFJTVk9FZ3NkRXFhbnpkbVZwOHFaU2lSM1RUMlRYYWkzbzNZZld0OFNwR0FvYlhvbjZjWXlxTXlVM0g5cVFLSTAyY2JKTHpLeHF1SHhsR0kyaWRUY3hBMm5KSHBTQmVMVDV3TGtWdmdYR05GUGZ1YmpBRG5xRW9KMkFsRXNqamFwalQ1d0gtWEtVVlU3WVV3TlcybkFNODhKOFBYd1AxTkZ3dmxsZjRSR3QwMlJIc0h1U005Rm5UaHJqLWs0di16SlVOZ2pBLTA1THo0SlV1V3ljaExSczJuVnBJc2p3NmprcnRvR0Z4cWtWS2tjelJrOTZTWjhSWUNxWUJVNTVWUl80T1RQNVZJUHNCekpVdWtzUXltemx5QjlFUWVYZXJiejJiUXdoZXhaLWRmRzc1aHRpMmszNFZON1lGUGcuWEdob2RkNWdGR2FQV0N4bXB4V3pLdw.NJAZW1WLq7rsF9zoiKlseyV0xNejNM6Iq0GyhvBr1JU"
}
2. email validation code flow
curl -X POST \
'https://localhost:8443/openidm/selfservice/registration?_action=submitRequirements' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-H 'X-OpenIDM-Password: anonymous' \
-H 'X-OpenIDM-Username: anonymous' \
-d '{
"token": "eyJ0eXAiOiJKV1QiLCJjdHkiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.ZXlKMGVYQWlPaUpLVjFRaUxDSmxibU1pT2lKQk1USTRRMEpETFVoVE1qVTJJaXdpWVd4bklqb2lVbE5CTVY4MUluMC5OSm8zTTYyNTdoazJPUDNIYmRUMzNtT0VOc1p0a0xmaHAwazBZc2dZVEdSUVFrZzFQYjZYUEdITlBQdE1sU1FZTGxoQkEyZkJ0V3Y3WEIwUzhCTWlQMHFoN3NBT1p6U0JSSGgtczFEeWhENE5oSU45NzU4dmNyeFp2bjFMTUxHYi1EenFnR1FKRXFvcHR6SU1FcGFWTElvLTdJR1BxMjd0bFRGVDBWQTZsMi1mSVZTaVptT1pVZkNKM1Z6c1kzWk9VczcwLWlNdDZLcWZCZF8zOGVUV1RzQ0ZNZGRrT3dsNmRpOUlJSXRLTmt4RDFzaDZPSUthbDVPVFc1RFY5LXhDRUJxYVhrUFMwWV9JTGpFMFdsWDdPaWxFVm0xRG5CeUp1aDBfZkQxd1hERHExYWZJTVhNSWdTYTVNaEpGNnNtMFRiblJnWUo0NkhZczhScmRkZ1REWkEuYkxEdDZjb0JKWERScXJTWFJCemx0dy5QS2c3NGlhU1RQYnJfOXR2Y3BYTWoyVXMwUTJjR0JseW41X252NnFYYVpTb3hPOGV2aGkyLTZiT25wRXBsenAzQUY0MkZ1U0NYdHlYSmE2cmpJMjZIUXRwYzJMZGh6cGx0NGxvUXlfTmgxdFJWcTJuaWc2bDBjNEdiYVpsLVU5cVVCYkUxT09ac3dKbzhzNzlzSC0xMTlxZnVWZWxMUHNsVDhaTDcwZHhMNTdZal8wMlRUeUlNU3ZQT19uamxUdWFSUlJ0NDBYVHktX0FYTFphTzJkdXhaSWUyX1pWRDFxdGdKQ2ZOTTlKX1FZdU1MdklCRHZxSkZjSWxJbDVtcU5lSWpaZEVlOHp2c0F4VmFqcVhZNWtaZVdhVUVpamctZmZPT3E1ZV91eEZuV3ZYY2F3ZWRRZFFpVTBGcXJwRXpqcFY4R0JwdkUtQWd4Um5hSnl6Ry1wcXlKZnhYekp0ZzZlUkZaejVVUDVnNHZMTmhNWWN1Uko3WW1OYk1kRlB5RldwZlZ5Mmx2cWxvTTBaS0pKWVFLWU9Xc1hQR2x6UzFxSEFBTF9MWmFXbTVJQnozbmtVa2I3NHdLc18zWWlDZlJqREVMZVNIYlNENEdkR0h3cHlFMkFjNjVFdXpJQ1hNQVliRmRldXB2T3BFZHo3dTZTcWZqRkhCSC1BakRRdm5iellqY25Gdk81NmZDeHNfQTdwZzJWZXJEOFcyNWJfVC1MZHFXeVA3X09ZM2pQY3ZzdVd5aUlkVkRCOXlWWFg5TTAxRElFeWRzZkF0SjUzUElOYjZldUk0cnRnZWIwRXhVUTFqMWw1NkFUVS1iUkwzTU1WNWE5RVlCOEJsa1hoQWgzaWNiLTNSNVgyUU5qdzF6Z1lteFpIVFhLY1VabUxQNW1UblFkNHZRVGFvb2h1T2NxN3FvOGZBLUxtc2YwcU82NEM2OGNJb3FfUXFvck1WSFpPaHQ2ZXAyakxyaFlRbFVTOHNuVkw4dVgxQlVhNGFBRmY2by0xdjBJMkJ1QUhJYzhUU1hTRTdaaXp1bWhLcmtqa1R2M1h3UnItdFJTVk9FZ3NkRXFhbnpkbVZwOHFaU2lSM1RUMlRYYWkzbzNZZld0OFNwR0FvYlhvbjZjWXlxTXlVM0g5cVFLSTAyY2JKTHpLeHF1SHhsR0kyaWRUY3hBMm5KSHBTQmVMVDV3TGtWdmdYR05GUGZ1YmpBRG5xRW9KMkFsRXNqamFwalQ1d0gtWEtVVlU3WVV3TlcybkFNODhKOFBYd1AxTkZ3dmxsZjRSR3QwMlJIc0h1U005Rm5UaHJqLWs0di16SlVOZ2pBLTA1THo0SlV1V3ljaExSczJuVnBJc2p3NmprcnRvR0Z4cWtWS2tjelJrOTZTWjhSWUNxWUJVNTVWUl80T1RQNVZJUHNCekpVdWtzUXltemx5QjlFUWVYZXJiejJiUXdoZXhaLWRmRzc1aHRpMmszNFZON1lGUGcuWEdob2RkNWdGR2FQV0N4bXB4V3pLdw.NJAZW1WLq7rsF9zoiKlseyV0xNejNM6Iq0GyhvBr1JU",
"input": {
"code": "7952d2de-86e5-4d60-acfa-d6ccb4acfa8b"
}
}'
{
"type": "localAutoLogin",
"tag": "end",
"status": {
"success": true
},
"additions": {
"successUrl": "http://localhost:8080",
"credentialJwt": "eyJ0eXAiOiJKV1QiLCJjdHkiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.ZXlKMGVYQWlPaUpLVjFRaUxDSmxibU1pT2lKQk1USTRRMEpETFVoVE1qVTJJaXdpWVd4bklqb2lVbE5CTVY4MUluMC5pVWlGZlRBalJ5aEpKcU5HWGVYWGk0ZGxlN1VMZ21NVDBvNmxuWXlMYUhadE9QeWNMV3c5eG94UHdlTzFVQUhPRUVfMjlhTUw1TGtlbl9OLVhGX0pERFl4TmtfdjVXSE5kdTlzMk1WWWxIa2RoYkw1ejZzNEl4cGc2cDdJM0VTYXM2QVhRT2l5NTV4UGt2cHU4UUhSXzdiS1NNQV9FVGtHZ0ZVUE85bGFGTEpVd055Rll3NWhVTUVYdW0xOFBQOUJVVnlJNElnbC1Dc3NwQlZXZzBxc1hkNFNfUHRpWGpidjZHZGpFOVcxX25kekJuS1MyRGhUc3FMaTd6NnAwdE9tTnhld1l4bTRfODE0N0Y2dU55cEtXVTNNZFk4QkdZVU4yeGdlUG51b0VYYl92MXBrd3ljRFJfR0xBbFBZZ0ZFYVNJZWtyVlJVTVpGTDBlZmNXc3B4aUEuR2RZNUZYRm82aVAxQnIxMU04MGpudy52aV9YYlBVMHdFVWRWZG5HX2dHbmEycTc0dUxpYm90ZzVOcGk1MnhISXYtclRXRjNCRWFxTDFMdkRKN0lZVGZNaGZlREZWcXczM3JHOUxyaVBLOUxHc2JTWHE2ci1mTmhrM3hBV1FTMW1aSExrS1F4NDNmV29fRTBadUdySGVmeGNXaU4wWlY2OWNMZDNxNmlubk5vNGcuNzVfUjROR1BqOUpsN1g0WEVfUlEzUQ.s7VfRxaGwi-DPy1AhZSrXqS93syyoNyRHDKrE5u2Tes"
}
}
Multiple selfservice registration
(note taken from Jake) (this should work with all other selfservices like password reset as well)
multiple self-service registration endpoints can be configured, each pointing to their own managed objects. There are two stages you will need to change from the out-of-the-box configuration:
```{
"name" : "idmUserDetails",
"identityEmailField" : "mail",
"socialRegistrationEnabled" : true,
"identityServiceUrl" : "managed/user",
"registrationProperties" : [
"userName",
"givenName",
"sn",
"mail"
],
"registrationPreferences": ["marketing", "updates"]
}
and
{
"name" : "selfRegistration",
"identityServiceUrl" : "managed/user"
}```
Note the identityServiceUrl
You can save these two configurations as something like conf/selfservice-registrationEmployee.json and conf/selfservice-registrationConsumer.json Which would result in services exposed as /openidm/selfservice/registrationEmployee etc... For the respective policy behavior to work properly, you will need to also adjust policy.json Out of the box we ship this:
```{
"resource" : "selfservice/registration",
"calculatedProperties" : {
"type" : "text/javascript",
"source" : "require('selfServicePolicies').getRegistrationProperties()"
}
}```
You would need to change that to match your new service name, and be sure there is an entry for both
Finally, unfortunately it looks like there is a need to make a minor change to the out-of-the-box JS there. bin/defaults/script/selfServicePolicies.js hard-codes "getRegistrationProperties" to look for "config/selfservice/registration". This will need to be changed. I'll give you a diff you can use
The configuration path is now available as an argument With this change, your policy could look like this:
```{
"resource" : "selfservice/registrationEmployee",
"calculatedProperties" : {
"type" : "text/javascript",
"source" : "require('selfServicePolicies').getRegistrationProperties('config/selfservice/registrationEmployee')"
}
},
{
"resource" : "selfservice/registrationConsumer",
"calculatedProperties" : {
"type" : "text/javascript",
"source" : "require('selfServicePolicies').getRegistrationProperties('config/selfservice/registrationConsumer')"
}
}```
Terms & Conditions
T&C are stored in the internal repo and can be queried by
The terms and conditions config can be found here
curl -X GET \
'https://localhost:8443/openidm/managed/user?_queryFilter=userName+eq+'scarter'&_fields=*,/_meta/*' \
-H 'Cache-Control: no-cache' \
-H 'X-OpenIDM-Password: openidm-admin' \
-H 'X-OpenIDM-Username: openidm-admin'
{
"result": [
{
"_id": "scarter",
"_rev": "000000007091083d",
"mail": "scarter@example.com",
"givenName": "Steven",
"sn": "Carter",
"description": "Created By CSV",
"userName": "scarter",
"telephoneNumber": "1234567",
"accountStatus": "active",
"effectiveRoles": [],
"effectiveAssignments": [],
"postalAddress": "ttest",
"postalCode": "etst",
"city": "etwst",
"_meta": {
"_ref": "internal/usermeta/3698fec2-f406-419e-b9f8-8b092805464c",
"_refResourceCollection": "internal/usermeta",
"_refResourceId": "3698fec2-f406-419e-b9f8-8b092805464c",
"_refProperties": {
"_id": "4436d958-47c0-4a46-9b15-475b641ede38",
"_rev": "00000000a4a69d6b"
},
"createDate": "2018-06-19T12:26:30.258Z",
"lastChanged": {
"date": "2018-06-19T12:27:02.783Z"
},
"loginCount": 1,
"termsAccepted": {
"acceptDate": "2018-06-19T12:26:54.028Z",
"termsVersion": "1.0"
},
"stagesCompleted": [
{
"identifier": "1621838512",
"dateCompleted": "2018-06-19T12:27:02.960Z"
}
],
"_rev": "00000000071ba567",
"_id": "3698fec2-f406-419e-b9f8-8b092805464c"
}
}
],
"resultCount": 1,
"pagedResultsCookie": null,
"totalPagedResultsPolicy": "NONE",
"totalPagedResults": -1,
"remainingPagedResults": -1
}
Related articles
see also Password Reset per email