Password Policy Setting
How to implement Password complexity rule using the Update Tenant API
The Katsu platform Update Tenant API allows tenant administrators the flexible option to configure password settings. Here are some password related rules and task that tenant admin can perform:
- Implement the logic to enforce password complexity rules such as requiring uppercase letters, lowercase letters, numbers, and special characters.
- Validate user passwords against these rules during account creation, password change, or password reset processes.
- Provide feedback to users when their password does not meet complexity requirements.
- Check password history.
- Password length check.
In this simple to follow tutorial, I’ll illustrate how to enforce password complexity rule through the Update Tenant API on Katsu platform. Let’s quickly get started with the step-by-step guide to enforce password complexity rule.
- Step 1 (Create a tenant super admin): The first step to enforcing password complexity on Katsu platform is to create a tenant super admin. To create a tenant super admin, make a post request to this endpoint:
/api/v1/users/publicand pass the following as request body:
{
"username": "string",
"password": "string",
"tenantId": "string",
"role": "CUSTOMER",
"firstName": "string",
"lastName": "string",
"middleName": "string",
"country": {
"name": "string",
"code": "string",
"currency": "string"
},
"state": {
"name": "string",
"code": "string"
},
"city": {
"name": "string",
"code": "string"
},
"address": "string",
"foreignerCountry": {
"name": "string",
"code": "string",
"currency": "string"
},
"foreignerState": {
"name": "string",
"code": "string"
},
"foreignerCity": {
"name": "string",
"code": "string"
},
"photo": "string",
"identityType": "string",
"identityDoc": "string",
"actionBy": "string",
"dob": "string",
"gender": "MALE",
"phone": "string",
"alternatePhone": "string",
"bvn": "string",
"proofOfAddress": "string",
"driversLicense": "string",
"voterCard": "string",
"nin": "string",
"passportNumber": "string",
"isDistributor": false,
"isManufacturer": false,
"latitude": 0,
"longitude": 0,
"referralName": "string",
"referralPhone": "string",
"companyName": "string",
"tradeCategory": "AGRIC_COMMODITIES",
"metadata": {
"qualityRecordOfCrop": "string",
"essentialCertification": [
{
"certificateName": "string",
"docLinks": [
{
"link": "string",
"name": "string"
}
]
}
],
"noOfarmerInCluster": 0,
"familySizeOfarmer": 0,
"challengesOrNeeds": "string",
"farmSize": 0,
"harvestingAndPostHarvestingService": "string",
"farmLabourPractices": "string",
"environmentalPractices": "string",
"farmClusterInformation": "string",
"targetQuantityPerCycle": "string",
"qualityAndQuantityRecords": "string"
},
"isSendNotification": true,
"source": "SHOP"
}
The following are the required fields to create a tenant super admin:
| Data | Data type |
|---|---|
| username* | string |
| Password* | string |
| phone* | string |
| role* | RoleSignUpType[Enum] string |
| firstName* | string |
| lastName* | string |
| country* | string |
| ---------- | ------------ |
Note: Username must be a valid email and phone number must valid as well.
A sample request to create a tenant super admin:
curl -X 'POST' \
'https:baseURL/api/v1/users/public' \
-H 'accept: */*' \
-H 'Content-Type: application/json' \
-d '{
"username": "johndoe@email.com",
"password": "johndoe80",
"role": "TENANT_SUPER_ADMIN",
"firstName": "John",
"lastName": "Doe",
"phone" : "08085768453",
"country": {
"name": "Nigeria",
"code": "NG",
"currency": "NGN"
}
}
Sample response body upon tenant super admin creation:
{
"wallet": {
"createdAt": null,
"virtualBankCode": "035",
"virtualBankName": "Wema Bank"
},
"location": {
"coordinates": [
0,
0
],
"type": "Point"
},
"metadata": {
"essentialCertification": []
},
//userId
"_id": "6645c0eaf92bf744210ce370",
"__v": 0,
"appDefaultView": {
"TRACE": "NONE",
"LOFT": "NONE",
"KATSU": "NONE",
"SABI_MARKET": "NONE",
"PLATFORM": "NONE",
"DEAL": "NONE"
},
"businesses": [],
"bvnVerified": false,
"commodityActiveTraderStatus": "NONE",
"country": {
"name": "Nigeria",
"code": "NG",
"currency": "NGN",
"_id": "6645c0eaea4681e4925c7044"
},
"createdAt": "2024-05-16T08:16:42.667Z",
"createdBy": null,
"driversLicenseVerified": false,
"emailVerification": false,
"firstName": "John",
"hasPin": false,
"isDistributor": false,
"isForeigner": false,
"isManufacturer": false,
"lastName": "Doe",
"ninVerified": false,
"passId": "SLW-e97ca6c4abde4328f556202a67aacd",
"passportNumberVerified": false,
"password": null,
"permissions": [],
"phone": "08085768453",
"phoneVerified": false,
"profileOwners": [],
"roles": [
"TENANT_SUPER_ADMIN",
"TENANT_GLOBAL"
],
"status": "ACTIVE",
"tenants": [],
"type": "USER",
"updatedAt": "2024-05-16T08:16:42.667Z",
"username": "johndoe@email.com",
"voterCardVerified": false
}
- Step 2 (Login): The next step is to login as a tenant super admin to generate your authorization token. To login as a tenant super admin, make a post request to this endpoint:
/api/v1/users/login/publicand pass in the following required parameters: Username, password, and role. Upon successful login, you’ll receive an authorization token (acessToken) that you’ll use as bearer token token for the next stage. The next step is to create a tenant.
Sample login request:
curl -X 'POST' \
'https:baseURL/api/v1/users/login/public' \
-H 'accept: */*' \
-H 'Content-Type: application/json' \
-d '{
"username": "johndoe@email.com",
"password": "johndoe80",
"role": "TENANT_SUPER_ADMIN"
}
Sample response upon login:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2thdHN1cGF5LmNvbSIsInN1YiI6IktBVFNVLUFVVEhPUklaQVRJT04iLCJuYmYiOjE3MjMwMTM5NDUsImp0aSI6IjEyYWQzYzFiLTA1MzgtNDBhZS05OGZjLWUzNjY3NTMzNTAwYSIsInBsaWQiOiJLQVRTVS1DTE9VRC0yNjQ1ODliZC00ZDhhLTQ2MDgtOTA3Yi1kNWQyMjAwOTNjZDciLCJwbGVtIjoidGVjaEBrYXRzdXBheS5jb20iLCJwbHR0IjoiV0VCIiwicGxjZCI6IjY2NDVjMGVhZjkyYmY3NDQyMTBjZTM3MCIsInBsdGQiOiJOT1RfQVBQTElDQUJMRSIsInBsdG8iOiJSRUdJU1RSWSIsInBsaGgiOiJLVFM6MDYyNTYwOWMwZmY4YWMyODZlNjAiLCJfaWQiOiI2NjQ1YzBlYWY5MmJmNzQ0MjEwY2UzNzAiLCJjb3VudHJ5Ijp7Im5hbWUiOiJOaWdlcmlhIiwiY29kZSI6Ik5HIiwiY3VycmVuY3kiOiJOR04iLCJfaWQiOiI2NjQ1YzBlYWVhNDY4MWU0OTI1YzcwNDQifSwiZW1haWxWZXJpZmljYXRpb24iOnRydWUsImZpcnN0TmFtZSI6IkZyYW5rIiwibGFzdE5hbWUiOiJKYXkiLCJwYXNzd29yZCI6bnVsbCwicGhvbmUiOiIyMzQ4MTM5MjA3NjY4Iiwicm9sZXMiOlsiVEVOQU5UX1NVUEVSX0FETUlOIiwiVEVOQU5UX0dMT0JBTCJdLCJzdGF0dXMiOiJBQ1RJVkUiLCJ0ZW5hbnRzIjpbXSwidHlwZSI6IlVTRVIiLCJ1c2VybmFtZSI6ImZyYW5rLmpvc2VwaEBzYWJpLmFtIiwiaWF0IjoxNzIzMDEzOTQ1LCJleHAiOjE3MjM2MTg3NDV9.vvkPrhVzobHkAA3c01z-wm1z5_ikhB50WqE19VBZLD8",
"expireDurationSeconds": 604800,
"refreshToken": "69cc9940-212f-473c-9a49-8d9c92a4d55a"
}
Before we update the tenant password setting which is the main focus for this tutorial, we first need to create a tenant. That is the next step for this tutorial.
- Step 3 (Create a tenant): To create a tenant, you make a post request to this endpoint:
/api/v1/tenantsand pass the following required parameters: userId, name, and reuseExistKyb.
Note: The userId is autogenerated and is part of the response body you receive when you created a user Tenant super admin. reusExistKyb is a boolean with a default value of false.
Sample request body to create a tenant:
curl -X 'POST' \
'https:baseURL/api/v1/tenants' \
-H 'accept: */*' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2thdHN1cGF5LmNvbSIsInN1YiI6IktBVFNVLUFVVEhPUklaQVRJT04iLCJuYmYiOjE3MjMwMTM5NDUsImp0aSI6IjEyYWQzYzFiLTA1MzgtNDBhZS05OGZjLWUzNjY3NTMzNTAwYSIsInBsaWQiOiJLQVRTVS1DTE9VRC0yNjQ1ODliZC00ZDhhLTQ2MDgtOTA3Yi1kNWQyMjAwOTNjZDciLCJwbGVtIjoidGVjaEBrYXRzdXBheS5jb20iLCJwbHR0IjoiV0VCIiwicGxjZCI6IjY2NDVjMGVhZjkyYmY3NDQyMTBjZTM3MCIsInBsdGQiOiJOT1RfQVBQTElDQUJMRSIsInBsdG8iOiJSRUdJU1RSWSIsInBsaGgiOiJLVFM6MDYyNTYwOWMwZmY4YWMyODZlNjAiLCJfaWQiOiI2NjQ1YzBlYWY5MmJmNzQ0MjEwY2UzNzAiLCJjb3VudHJ5Ijp7Im5hbWUiOiJOaWdlcmlhIiwiY29kZSI6Ik5HIiwiY3VycmVuY3kiOiJOR04iLCJfaWQiOiI2NjQ1YzBlYWVhNDY4MWU0OTI1YzcwNDQifSwiZW1haWxWZXJpZmljYXRpb24iOnRydWUsImZpcnN0TmFtZSI6IkZyYW5rIiwibGFzdE5hbWUiOiJKYXkiLCJwYXNzd29yZCI6bnVsbCwicGhvbmUiOiIyMzQ4MTM5MjA3NjY4Iiwicm9sZXMiOlsiVEVOQU5UX1NVUEVSX0FETUlOIiwiVEVOQU5UX0dMT0JBTCJdLCJzdGF0dXMiOiJBQ1RJVkUiLCJ0ZW5hbnRzIjpbXSwidHlwZSI6IlVTRVIiLCJ1c2VybmFtZSI6ImZyYW5rLmpvc2VwaEBzYWJpLmFtIiwiaWF0IjoxNzIzMDEzOTQ1LCJleHAiOjE3MjM2MTg3NDV9.vvkPrhVzobHkAA3c01z-wm1z5_ikhB50WqE19VBZLD8' \
-H 'Content-Type: application/json' \
-d '{
"userId":"6645c0eaf92bf744210ce370",
"name":"johndoe@email.com",
"reuseExistKyb":false
}
Remember our focus in this tutorial is to update tenant password. The password setting is part of the response payload you receive when a tenant is successfully created.
Sample response body:
{
"code": "9a418930-c7a8-4cd8-8f15-1541dcde9207",
"name": "johndoe@email.com",
"tenantHandle": "john.doe",
"kycDetails": {
"businessDetails": {
"metadata": {
"isBusinessDeliveryPerformance": false,
"isKickBackPromised": false,
"isCompanyRegulated": false,
"isSharesListed": false,
"isCompanySubjectToInvestigation": false,
"isShareholderPoliticallyExposed": false
},
"directorsProofOfAddress": [],
"shareHoldersProofOfAddress": [],
"directorsProofOfIdentification": []
},
"status": "PENDING",
"additionalShareholdersDetails": [],
"guarantorDetails": []
},
"ipAddresses": [],
"domains": [],
"country": {
"name": "Nigeria",
"code": "NG",
"currency": "NGN",
"_id": "6645c0eaea4681e4925c7044"
},
"user": "6645c0eaf92bf744210ce370",
"wallet": {
"virtualBankCode": "035",
"virtualBankName": "Wema Bank",
"createdAt": null
},
"config": {
"logisticDeliverySetting": {
"isProviderSplitEnabled": false,
"isDropOffCodeEnabled": false,
"defaultProvider": "FLEET",
"deliveryFeeType": "RATECARD",
"providerSplits": []
},
"merchantSetting": {
"priceMargin": {
"type": "PERCENT",
"value": 0,
"enabled": false
},
"isMovEnabled": false
},
"deviceSettings": {
"isAllowMultipleDevice": false,
"maxDevicesAllowed": 1,
"idleLogoutEnabled": false,
"autoSignOutLeastActiveDevice": true
},
"passwordSettings": {
"isPasswordExpirationEnabled": false,
"passwordExpirationValue": 3,
"passwordExpirationPeriod": "MONTHS",
"isPasswordHistoryCheckEnabled": false,
"passwordHistoryLimit": 5,
"isPasswordComplexityCheckEnabled": true,
"passwordMinLength": 8,
"passwordRequiresUppercase": true,
"passwordRequiresLowercase": true,
"passwordRequiresNumbers": true,
"passwordRequiresSpecialCharacters": true
},
"isBusinessNameFormatted": false,
"isProductNameFormatted": false,
"isUniqueBusiness": false,
"isUniqueUser": false,
"isEnforceKYBErrorOnFailedVerification": false,
"isOutOfStockVisible": false,
"isAllowProductVisibleOnCreate": false,
"isAllowLogisticEnabledOnOrder": false,
"isAllowLogisticOnDistributorOrder": false,
"isAllowLogisticOnManufacturerOrder": false,
"isAllowLogisticOnWholesalerOrder": true,
"isAllowPickupAddressSentOnOrder": false,
"isWholesalerDisableOnCreate": false,
"isDistributorDisableOnCreate": false,
"isManufacturerDisableOnCreate": false,
"isEnableLocalWallet": false,
"isEnableWalletPaymentForDistributor": false,
"isEnableWalletPaymentForManufacturer": false,
"isEnableWalletPaymentForWholesaler": true,
"merchantInventorySettlementStatus": "DELIVERED",
"wholesalerDefaultLocationRadius": 40,
"distributorDefaultLocationRadius": 40,
"manufacturerDefaultLocationRadius": 40,
"isEmailVerificationRequired": false,
"quad": "QUAD_1"
},
"deleted": false,
"rotationPeriod": "YEARS",
"rotationValue": 2,
"createdBy": "6645c0eaf92bf744210ce370",
"deletedBy": null,
"updatedBy": null,
"deletedAt": null,
"holidayStartDate": null,
"holidayEndDate": null,
"bannerLinks": [],
"isBannerEnabled": false,
"_id": "66b31de103aefa18f4945bbc",
"services": [],
"products": [],
"createdAt": "2024-08-07T07:10:25.301Z",
"updatedAt": "2024-08-07T07:10:25.301Z",
"__v": 0
}
In the above response payload, the passwordSettings object is our focus
...
"passwordSettings": {
"isPasswordExpirationEnabled": false,
"passwordExpirationValue": 3,
"passwordExpirationPeriod": "MONTHS",
"isPasswordHistoryCheckEnabled": false,
"passwordHistoryLimit": 5,
"isPasswordComplexityCheckEnabled": true,
"passwordMinLength": 8,
"passwordRequiresUppercase": true,
"passwordRequiresLowercase": true,
"passwordRequiresNumbers": true,
"passwordRequiresSpecialCharacters": true
}
...
- Step 4 (Update tenant passwordSettings): Now that we’ve successfully created a tenant, the next step is set password policy. To update a tenant password setting, make a Put request to this url
/api/v1/tenants{tenantId}.
Sample request body:
{
"userId": "6645c0eaf92bf744210ce370",
"config": {
...
"passwordSettings": {
"isPasswordExpirationEnabled": true,
"passwordExpirationValue": 3,
"passwordExpirationPeriod": "WEEKS",
"isPasswordHistoryCheckEnabled": true,
"passwordHistoryLimit": 1,
"isPasswordComplexityCheckEnabled": true,
"passwordMinLength": 8,
"passwordRequiresUppercase": true,
"passwordRequiresLowercase": true,
"passwordRequiresNumbers": true,
"passwordRequiresSpecialCharacters": true
},
...
}
}
Note: The config object consist of other items. However, I removed them because our focus is on the passwordSettings object. If you notice, I have changed some of the values of the fields and updated them to what you have above.
Explanation of each field:
-
passwordExpirationValue: This field sets the duration time for password expiration.
-
isPasswordExpirationEnabled: When this field is set to true, the user password should be expire at the value set for
passwordExpirationValue. passwordExpirationPeriod: This sets the expiration period of user password. It can be set to HOURS,DAYS,WEEKS,MONTHS,YEARS. -
isPasswordHistoryCheckEnabled: When this field is set to true, it checks for the password history of the user to ensure that passwords used within a month or more cannot be reused by the user.
-
passwordHistoryLimit: This field sets the password history duration check in months. For example. When we set
passwordHistoryLimitto 1, it means, passwords used within the last one month should not be reused by the user. -
isPasswordComplexityCheckEnabled: When this field is set to true, it ensures all passwords used by the user must follow the complexity rules set for it. For example, the use of uppercase, lowercase, etc.
-
passwordMinLength: This field sets the minimum length a user password must have
-
passwordRequiresUppercase: When this field is set to true, it ensures all passwords must contain at least an uppercase letter.
-
passwordRequiresLowercase: When this field is set to true, it ensures all passwords must contain at least a lowercase letter.
-
passwordRequiresNumbers: When this field is set to true, it ensures all passwords must contain at least a number.
-
passwordRequiresSpecialCharacters: When this field is set to true, it ensures all passwords must contain at least a special character.
Conclusion
In this tutorial, we explored some password setting policy related tasks and successfully illustrated how to update password policy.