Access to users roles from a service account - keycloak

I tryied without success to fetch users roles from a service account. This is my configuration:
realm: realmA
client: app-a
roles: ['operator', 'manager']
user: user-a
roles on app-a: 'operator'
From other stack questions I know that I need to:
Make the client 'confidential'
Activate the service account for the client
give to the service account the roles realm-management -> query-users and realm-management -> view-users
Now I can ask KC an access token for my app-a service account to the end-point <KC URL>/realms/realmA/protocol/openid-connect/token and with this access token ask users data to this end-point <KC URL>/admin/realms/realmA/users after that I can retrieve my users list that has this shape:
[
{
id: '10f5c814-1474-4ed0-9985-99b928cead3b',
createdTimestamp: 1646751082376,
username: 'username',
enabled: true,
totp: false,
emailVerified: true,
firstName: 'TheName',
lastName: 'LastName',
email: 'my#company',
attributes: { time_intervals: [ '8-13' ] },
disableableCredentialTypes: [],
requiredActions: [],
notBefore: 0,
access: {
manageGroupMembership: false,
view: true,
mapRoles: false,
impersonate: false,
manage: false
}
}
]
Now I want to inspect the users roles at least the roles that the user has inside the client app-a but after hours and hours I can't figure out a way to do that. What is the correct way to do that?

Now I want to inspect the users roles at least the roles that the user
has inside the client app-a
For that try the endpoint:
<KC URL>/realms/realmA/users/<USER ID>/role-mappings/clients/<ID OF THE CLIENT>
In your case the <ID OF THE CLIENT> will be the id of the app-a.

Related

Azure AD B2C keeps providing v1 tokens not v2 tokens

Azure's AD B2C keeps issuing v1 tokens even though v2 tokens are configured in the manifest of the SPA app that's registered:
{
"id": "XXX",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": null,
...
}
The client uses #azure/msal-angular v2.0.5 (along with #azure/msal-browser v2.19.0) to request the token via a plain MSAL Interceptor:
export const protectedResourceMap: Map<string, Array<string>> = new Map([
[
urlJoin(configs.apiUri, 'screen'),
[configs.authConfig.scope.screen_access],
],
]);
#NgModule({
imports: [
MsalModule.forRoot(
new PublicClientApplication({
auth: {
clientId: '...',
authority: 'https://login.microsoftonline.com/XXX.onmicrosoft.com',
postLogoutRedirectUri: '.../logout',
navigateToLoginRequestUrl: true,
redirectUri: '.../auth',
},
cache: {
cacheLocation: 'sessionStorage',
},
}),
{
interactionType: InteractionType.Redirect, // Popup or Redirect
loginFailedRoute: '/login-failed'
},
{
interactionType: InteractionType.Redirect, // Popup or Redirect
protectedResourceMap,
})
...
This seems to look OK, especially the "accessTokenAcceptedVersion": 2.
What might be the root cause of the token still being of v1?
{
"aud": "00000003-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"iss": "https://sts.windows.net/7dcXX-XXXXX.../",
...
"ver": "1.0",
...
}
Pointers would be much appreciated.
Azure AD B2C only ever used the endpoint when making the OIDC Authentication requests with v2.0, a v1.0 never existed. So it always has issued v1.0 tokens (v2 is the first and only version). This is completely normal.
Only Azure AD had v1.0 and v2.0 OIDC endpoint, and therefore maps based off of accessTokenAcceptedVersion.
You don't need to mess with this property in AAD B2C application registrations unless you have a SAML relying party.

Local Keycloak setup returns "Error: unable to verify the first certificate" nodejs error

Trying to use Keycloak as SSO running within Kubernetes cluster on minikube to authenticate demo nodejs app:
var express = require('express');
var session = require('express-session');
var Keycloak = require('keycloak-connect');
var cors = require('cors');
var app = express();
app.use(cors());
const memoryStore = new session.MemoryStore();
app.use(session({
secret: 'some secret',
resave: false,
saveUninitialized: true,
store: memoryStore
}));
var keycloakConfig = {
"realm": "Demo-Realm",
"auth-server-url": "https://keycloak.192.168.49.2.nip.io/auth/",
"ssl-required": "external",
"resource": "nodejs-microservice",
"verify-token-audience": true,
"credentials": {
"secret": "14de3a01-5c15-42fd-aa6a-fcc35c0961ff"
},
"use-resource-role-mappings": true,
"confidential-port": 0,
"policy-enforcer": {}
};
const keycloak = new Keycloak( { store : memoryStore }, keycloakConfig );
app.use(keycloak.middleware({
logout: '/logout',
admin: '/'
}));
app.get('/user', keycloak.protect('user'), function(req, res){
res.send("Hello User");
});
app.listen(3000, function () {
console.log('Started at port 3000');
});
But getting Access denied page when accessing http://localhost:3000/user with NodeJS console error: Could not obtain grant code: Error: unable to verify the first certificate
I have Demo-Realm realm created in Keycloak with such settings:
nodejs-microservice client:
Access Type: confidential
Valid Redirect URIs: http://localhost:3000/*
Authorization Enabled: ON
Roles: [ 'user', 'admin' ]
No login redirects happening (basic example works properly though). What could be the problem? How can I secure my NodeJS microservice with Keycloak?
Problem is somehow related to default self-signed certificate on Keycloak side. People recommend spending some time on obtaining proper certificate.
Can be temporary solved by muting certificate verification on NodeJS side with placing such line before api/express calls:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;

Not able to create user using keycloak api

Getting token is successful:
Post: http://localhost:8180/auth/realms/public-library/protocol/openid-connect/token
Content type:application/x-www-form-urlencoded
Body:x-www-form-urlencoded
client_id:spring-boot-app
username:pooja.kumawat
password:poojakumawat#23
grant_type:password
Output:Token
Creating a user is getting an error:
Post : http://localhost:8180/auth/public-library/users
Authorization:Bearer+Token
Content type:Application/Json
Body:Raw
{
"username": "name",
"enabled": true,
"emailVerified": false,
"firstName": "first",
"lastName": "last",
"credentials": [
{
"type": "password",
"value": "newPas1*",
"temporary": false
}
]
}
Error is:
{
"error": "RESTEASY003210: Could not find resource for full path: http://localhost:8180/auth/public-library/users"
}
It looks like you are using the wrong endpoint, change it to
http://localhost:8180/auth/admin/realms/public-library/users
And keep in mind, the user who is performing the POST request need to have at least the manage-users realm-management role assigned. Otherwise the response will be 403 Forbidden
What you need to do is go to the realm you are using in keycloak. Then go to the users section and select the user you are you using for the request. Under role Mappings, select realm management and assign this user the role realm admin and manage users role. After that, you will be able to make requests

Login if "Required User Actions" is existing

i have the following problem if an existing keycloak user has one or more required user action.
We use the keycloak (3.4.2.Final) rest api to login into keycloak. But keycloak returns always code 401 (invalid_grant) if user locked out or any required user action exists. So i can not identify what the main problem is.
For lockout i don't need to verify user's password, with any password (calling attackdetection rest api) can i tell the end user that the account is locked BUT for the required user actions not the same, user has to login successfully then can i handle next steps.
For example UPDATE_PASSWORD:
Login with username/password -> Login successfully OR username/password validated -> handle user action -> update password -> user logged in
I would appreciate any ideas.
Just in case someone still cares about an answer:
You can update the User using keycloak's admin REST api.
PUT /auth/admin/realms/myrealm/users/myKeycloakUserId
{
"id": "myKeycloakUserId",
"createdTimestamp": 1547730135139,
"username": "myusername",
"enabled": true,
"totp": false,
"emailVerified": true,
"firstName": "myfirstname",
"lastName": "mylastname",
"email": "myemail",
"attributes": {
"privacyStatementAcceptedDate": [
"2019-01-17T13:02:15.189Z"
],
"welcomeEmailDate": [
"2019-01-17T13:02:30.370Z"
],
"gender": [
"female"
],
"legalAgeConfirmedDate": [
"2019-01-17T13:02:15.189Z"
],
"termsAcceptedDate": [
"2019-01-17T13:02:15.189Z"
]
},
"disableableCredentialTypes": [
"password"
],
"requiredActions": [],
"notBefore": 0,
"access": {
"manageGroupMembership": true,
"view": true,
"mapRoles": true,
"impersonate": true,
"manage": true
}
}
Someone might want to try to send only the requiredActions-property instead of all other values (since these should be retrieved first), but I don't know if this would actually work. I thought: Better safe than sorry, so I retrieve the data first and then I only set the requiredActions-property to an empty array and send it back.
If you are using the Java client library (keycloak-admin-client), you might do it like this:
org.keycloak.admin.client.Keycloak keycloak = KeycloakBuilder.builder()
.serverUrl(KEYCLOAK_ADMIN_BASEURL))
.realm(KEYCLOAK_ADMIN_REALM))
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(KEYCLOAK_ADMIN_CLIENTID))
.clientSecret(KEYCLOAK_ADMIN_CLIENTSECRET))
.build();
final UserResource keycloakUserResource = keycloak.realm(
configurationService.getValue(KEYCLOAK_ADMIN_REALM)).users().get(
keycloakUserId);
//load the users user-representation from Keycloak
final UserRepresentation userRepresentation = keycloakUserResource.toRepresentation();
if (userRepresentation == null) {
throw new Exception("Failed to load the UserRepresentation for the current User");
}
//adapt the user-representation
userRepresentation.setRequiredActions(Collections.emptyList());
//update user in Keycloak
keycloakUserResource.update(userRepresentation);

How to change my mongoDB user password as non administrator?

I understand I can change a user's password by running db.changeUserPassword() as an MongoDB administrator. However, as a user with no administrator privilege, can I change my password just with my own account?
Thanks,
Although solution provided by Gergo worked. But I had to create a new role in order for it to work. I thought changeOwnPassword should be a built in privilege and not require additional admin work. Creating a dedicated role just for the purpose to be able to change user's own password is overkill in MongoDB.
If you have the necessary privileges, you can change your own password. You can verify that you have the necessary privileges by running this command:
db.runCommand(
{
usersInfo:"username",
showPrivileges:true
}
)
If it contains changeOwnPassword, then you can change the password:
db.runCommand(
{ updateUser: "username",
pwd: "password"
}
)
You can find more information in the MongoDB documentation.
In the admin database, create a new role with changeOwnPassword action.
use admin
db.createRole(
{ role: "changeOwnPasswordRole",
privileges: [
{
resource: { db: "", collection: ""},
actions: [ "changeOwnPassword" ]
}
],
roles: []
}
)
create a new user with changeOwnPasswordRole role and along with other roles
use test
db.createUser(
{
user:"user123",
pwd:"12345678",
roles:[ "readWrite", { role:"changeOwnPasswordRole", db:"admin" } ]
}
)
login the above user credentials
Use the below command to update own password
db.updateUser("user123",{pwd: "pass123"})