Keycloak REST API in UserRepresentation model there is a "credentials" property, which has ( type = "password", value="some", temporary=true/false }
On adding new user I wonna force the user to change his password on the first login. I know that it can be done globally in Required Actions in Realm/Authorization options, but if "force changing password" is not setted as default. I thought to control it by the setup that property in user.credentials model, but looks like it's totally dummy property and not makes any effect, always works as false. Am I right ?
P.S. I also take a look at the model in https://github.com/keycloak/keycloak/blob/b4b3527df7656bfaaee351ec414e56c683c134c2/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java I fond in resetPassword it's setted up, but not in updateUser ( which I assume is used for add user also ).
{
"username": "New_User_3",
"enabled": true,
"firstName": "NewUserDemoFirst",
"lastName": "NewUserDemoLast",
"email": "New_User_3#mail.test",
"attributes": {
},
"access": {
"manageGroupMembership": false,
"view": false,
"mapRoles": false,
"impersonate": false,
"manage": false
},
"credentials": [
{
"type": "password",
"temporary": true,
"value": "xM0K+G"
}
]
}
You could add required actions to the JSON object as shown. This would force the user to update the password upon login for the first time.
{
"username": "userxyz",
"credentials": [
{
"type": "password",
"value": "passwordabc",
"temporary": true
}
],
"requiredActions": [
"UPDATE_PASSWORD"
],
...
}
but looks like it's totally dummy property and not makes any effect, always works as false. Am I right ?
Yes.
This seem to be a bug of Keycloak. I can reproduce it too.
To fix the bug, I think the following lines should be added to org.keycloak.services.resources.admin.UserResource.updateUserFromRep():
List<CredentialRepresentation> credentials = rep.getCredentials();
if (credentials != null) {
for (CredentialRepresentation credential : credentials) {
if (CredentialRepresentation.PASSWORD.equals(credential.getType())
&& credential.isTemporary() != null && credential.isTemporary()) {
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}
}
}
A workaround is to call reset-password after creating a user.
PUT /{realm}/users/{id}/reset-password
See also:https://www.keycloak.org/docs-api/7.0/rest-api/index.html
Related
I have tested successfully idtokenhint demo and I am trying unsucessfully attestation verifiable credentials type , similar to the Woodgrave Employee Onboarding Demo, is this code available in c#?
In my case I need the Authenticator to request the VerifiedCredentialExpert VC first but I don't see how to trigger this on Authenticator, I tried this on issuance_request_config.json file, I also tried adding requestedCredentials to type VerifiedCredentialExpert as you see below to suggest to Authenticator to get this first, but didn't change the error behaviour:
"includeQRCode": false,
"callback": {
//In this sample code we will overwrite the callback and use the HOSTNAME dynamicall
//make sure you use ngrok or something like that when running on a local devbox.
//The MS AAD VC Request service needs to be able to reach the callback URI
"url": "https://YOURPUBLICREACHABLEHOSTNAME/api/issuer/issuanceCallback",
"state": "STATEWILLBESETINCODE",
"headers": {
"api-key": "OPTIONAL API-KEY for ISSUANCE CALLBACK API"
}
},
//The Authority is the DID from your MS AAD Verifiable Credential service, you can copy this from the VC page in azure portal
"authority": "did:ion: THIS IS YOUR DID FROM THE VC PAGE IN AZURE PORTAL WHICH IS SET IN THE SAMPLE BY COPYING THE VALUE FROM APPSETTINGS.JSON ",
"registration": {
"clientName": "Verifiable Test Register Verifiable Credential"
},
//The type needs to be the same as defined in the rules json definitione. The manifest can be copied after the credential has been
//created in the azure portal
"type": "VerifiedTestRegistration",
"manifest": "CREDENTIAL URL IN THIS SAMPLE WILL BE COPIED FROM APPSETTINGS.JSON",
//Recommendation is to protect issuance payload with a PIN code.
//The pincode is set to a random value in code and will be displayed in the UI to the user
"pin": {
"value": "123456",
"length": 4
},
//This is an example payload which will be used in the rules file of the credential.
//The rules files maps information from the ID Token (hint) to the VC
"claims": {
"country_of_registry": "",
"registration_number": "",
},
//You can request multiple verifiable credentials at once that's whty the requestCredentials is an array
"requestedCredentials": [
{
"type": "VerifiedCredentialExpert",
"purpose": "Required presentation of verifiable credentials expert to get Test Registration card.",
//You can trust multiple issuers who might be issuing the same credential type (for example certifications or diplomas)
//You need to specify at least 1 trusted issuer DID, for this sample code we copy the IssuerAuthority from appsettings to the request
//"acceptedIssuers": [ "did:ion: copied from your VC portal in this sample the code copies it from APPSETTINGS.JSON" ]
"acceptedIssuers": [ "theaccepetedidissuer" ]
}
]
}
These are the display and rules:
Display definition
{
"locale": "en-US",
"card": {
"title": "Test Verified Credential",
"issuedBy": "TheIssuer",
"backgroundColor": "#000000",
"textColor": "#ffffff",
"logo": {
"uri": "https://example.com/image.png",
"description": "Test Verified Credential"
},
"description": "Use this card to verify."
},
"consent": {
"title": "Do you want to get your Test Verified Credential?",
"instructions": "Sign in with your Verified Credential Expert Card to get your card."
},
"claims": [
{
"claim": "$.vc.country_of_registry",
"label": "Country of Registry",
"type": "String"
},
{
"claim": "$.vc.registration_number",
"label": "Registration Number",
"type": "String"
}
]
}
Rules definition:
{
"attestations": {
"presentations": [
{
"mapping": [
{
"outputClaim": "firstName",
"required": true,
"inputClaim": "$.vc.credentialSubject.given_name",
"indexed": false
},
{
"outputClaim": "lastName",
"required": true,
"inputClaim": "$.vc.credentialSubject.family_name",
"indexed": false
}
],
"required": true,
"credentialType": "VerifiedCredentialExpert",
"contracts": [
"https://verifiedid.did.msidentity.com/v1.0/tenants/id/verifiableCredentials/contracts/abcd/manifest"
],
"trustedIssuers": [
"did:ion:thedid"
]
}
],
"idTokenHints": [
{
"mapping": [
{
"outputClaim": "countryOfRegistry",
"required": true,
"inputClaim": "$.country_of_registry",
"indexed": false
},
{
"outputClaim": "registrationNumber",
"required": true,
"inputClaim": "$.registration_number",
"indexed": true
}
],
"required": true
}
]
},
"validityInterval": 2592000,
"vc": {
"type": [
"VerifiedTestRegistration"
]
}
}
I am testing on iphone12 pro latest iOS version installed.
Question as posted in this git project but unfortunately got no help.
Thank you for your help, Sergio
I'm using App ID and I follow this tuts https://cloud.ibm.com/docs/services/appid?topic=appid-tutorial-roles for my personal project.
I tried to call API {{APPID_MANAGEMENT_SERVER_HOST}}/management/v4/{{APPID_TENANT_ID}}/users with body:
"idp": "cloud_directory",
"idp-identity": "huynhdn#gmail.com",
"profile": {
"attributes": {
"role": "MANAGER"
}
}
}
I get Future User in User Profiles! => OK
Next, I call {{APPID_MANAGEMENT_SERVER_HOST}}/management/v4/{{APPID_TENANT_ID}}/cloud_directory/Users to set password for this user.
"displayName": "Test User",
"password": "abcd1234",
"emails": [
{
"value": "huynhdn#gmail.com",
"primary": true
}
]
}
Finally, I call {{APPID_AUTH_SERVER_HOST}}/oauth/v4/{{APPID_TENANT_ID}}/token to get token with user created above! But when i check in app id, attribute "role" is gone :(
WHY? or Anyone can help me another way to create user has "username", "password", "attribute" with API management!
The doc page you're referencing above states that in order to get future user attribute the user must validate ownership over email. You can either do it through standard means, or manually specifying status:confirmed when creating your CLoud Dir user, e.g.
{
"displayName": "John Smith",
"password": "p4ssw0rd",
"emails": [
{
"value": "john#example.com",
"primary": true
}
],
"status":"CONFIRMED"
}```
I am creating a web application using MongoDB and Go, which includes role based access control. I am storing the information regarding this in 2 collections, permissions and roles.
This is how these two collections look like.
Permissions
{
"operation": "create",
"resource": "project"
}
{
"operation": "read",
"resource": "project"
}
{
"operation": "update",
"resource": "project"
}
{
"operation": "delete",
"resource": "project"
}
{
"operation": "create",
"resource": "user"
}
resource is something on which an operation is performed. So if there is some operation which cannot be performed on some resource, then, I needn't store it. For example user can only be created hence only create user need to be stored.
Currently there are only 4 operations(create, read, update, delete) in the scope of the application, but could increase, like upload could come into picture.
Roles
{
"role": "admin",
"display_name": "Administrator",
"permissions": [
{
"operation": "create",
"resource": "project"
},
{
"operation": "read",
"resource": "project"
},
{
"operation": "update",
"resource": "project"
},
{
"operation": "delete",
"resource": "project"
}
]
}
Roles contain role, the name of role to be displayed on UI and the set of permissions that role has.
I need to send this information to UI using a REST API in a specific format, which would describe whether a specific role can perform an operation on a resource or not using the checked flag and whether a specific operation on a resource is editable or not by using the flag isEditable.
For example the permissions collection doesn't contain an operation delete on resource user, so it should not be editable, hence flag is set to false. Similarly user can be created, hence it is set to true.
{
display_name: "System Administrator",
role: "admin",
permissions: [
{
resource: "user",
privilages: {
create: { checked: false, isEditable: true },
delete: { checked: false, isEditable: false },
update: { checked: false, isEditable: false },
read: { checked: false, isEditable: false }
}
},
{
resource: "project",
privilages: {
create: { checked: true, isEditable: true },
delete: { checked: true, isEditable: true },
update: { checked: true, isEditable: true },
read: { checked: true, isEditable: true }
}
}
]
}
Is it possible to perform this using mongo aggregations? Or do I need to make modifications in my schema, If yes, then what modifications should I make.
I was able to solve the problem in 3 steps:
Include all the permissions for every role and add a flag called checked. This increased data redundancy but that wasn't a big issue.
Do a group by on resource field in roles collection.
Populate the missing privileges for every resource with isEditable set to false on server side.
I had to traverse the data on server side, but this was the most efficient way I could think of.
I am not sure what is going wrong with the create user api with roles.
Observations:
When fired without the roles it works fine, the payload is given below
{
"fullName": "unittestuser",
"emailAddress": null,
"enabled": true,
"password": "39HN=K?E",
"roles": null
}
when same endpoint is invoked with the addition of roles then it fails giving the http error code 400 (bad request)
{
"fullName": "unittestuser",
"emailAddress": null,
"enabled": true,
"password": "39HN=K?E",
"roles": [
{ "name": "unittest" },
{ "name": "UsernamePasswordAuthentication" },
{ "name": "Platform_NamedUser" },
{ "name": "Platform_Anyone" },
{ "name": "Platform_Metadata_MetadataInitializeUser" }
]
}
The roles part works when the default roles shipped with JasperReports Server installation are sent.
{
"fullName": "unittestuser3",
"emailAddress": null,
"externallyDefined": false,
"enabled": true,
"password": "39HN=K?E",
"roles": [
{ "name": "ROLE_USER" },
{ "name": "ROLE_ADMINISTRATOR" }
]
}
I have checked the the new roles which I have created are present on the JR Server before the create user is hit, so I am not sure what is going wrong with the newly created roles. I am using REST api v2 for role creation as well as user creation.
I have also tried creation the user first with empty roles and then adding roles the update call still fails with the same error.
Let me know if anyone has a clue.
Fixed...the new 6.0 on wards requires tenantid to be passed with the name of the role.
So instead of:
{ "name": "unittest" }
I passed: { "name": "unittest", "tenantId": "myorg" }
I am having trouble setting up an admin Role within the loopback project with mongodb. I've set up a simple model, added acls, created a user and associated the user with the admin Role but I can't access the model through the API Explorer - it always comes back with "Authorization Required".
Here are the steps I took:
1) I added model test through slc:
slc loopback:model
? Enter the model name: test
? Select the data-source to attach test to: moti_db (mongodb)
? Select model's base class: PersistedModel
? Expose test via the REST API? Yes
? Custom plural form (used to build REST URL):
Let's add some test properties now.
Enter an empty property name when done.
? Property name: name
? Property type: string
? Required? No
2) create user through Sign Up page: id = 1
3) create admin Role through API: id = 1
4) changed Role and RoleMapping to public=true so I could set them through the rest api
Here's the test data model:
{
"name": "test",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string"
}
},
"validations": [],
"relations": {},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "admin",
"permission": "ALLOW"
}
],
"methods": []
}
Here's the Role
{
"id": 1,
"name": "admin",
"created": "2015-05-22T19:45:23.887Z",
"modified": "2015-05-22T19:45:23.887Z"
}
Here's the RoleMapping:
{
"id": 1,
"principalType": "USER",
"principalId": "1",
"roleId": 1
}
Did you set an Authorization Token at the top of the Explorer? You need to call User.login() with an email and password, then set the Auth Token to the returning auth ID value. Then this token is sent with all subsequent calls (as an authorization: header value and allows you to make calls that require auth.
Another helpful thing is to run the API with ACL debugging, you can do
DEBUG=loopback:security slc run
and it will show you how it determines access. Maybe the output will be helpful (paste it here). Otherwise it's just a guess as your code looks good and assuming you've previously logged in and are using a token.