Keycloak uma-grant type tickets for service accounts do not seem to work with policies - permissions

I am trying to use the Keycloak AuthzClient to register resources and related permissions in a resource server.
I have a resource server "resourceserver" with authz service enabled.
Using the AuthzClient, initialized with the json file containing the resource server's client id and secret, I'm able to obtain a pat.
...
authzClient.obtainAccessToken().getToken();
ResourceRepresentation resource = new ResourceRepresentation();
resource.setName("myresource");
resource.setUris(new HashSet<>(Collections.singletonList("urn:resourceserver:resourcetype1:myresource")));
resource.setOwnerManagedAccess(true);
resource.setType("urn:resourceserver:resourcetype1");
resource.addScope("read", "write");
resource = authzClient.protection(pat).resource().create(resource);
UmaPermissionRepresentation permissionRepresentation = new UmaPermissionRepresentation();
permissionRepresentation.setName("myresourcepermissions");
permissionRepresentation.setDescription("foo");
permissionRepresentation.addRole("somerole");
UmaPermissionRepresentation result = authzClient.protection(pat).policy(resource.getId()).create(permissionRepresentation)
After executing this code, I can see, in the keycloak admin UI, that the resource has been created, and the scopes, however the policy/permission don't seem to show up.
I believe it is probably intended, as this keycloak admin UI only shows policies of types client, role, js, etc., but not "uma" which is what UmaPermissionRepresentation creates.
I can however see that policy exists in Keycloak by querying authz/protection/uma-policy with my pat.
So there is something there. Now testing it. I created a regular user and assigned it the realm role somerole. Using this user and some arbitrary public client, I'm able to get an RPT.
First getting an access token using the password grant:
grant_type=password&username=joe&password=password&client_id=somepublicclient
Then exchanging that for an RPT:
grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&audience=resourceserver
The RPT comes back and if I view its contents, I can see the authorization block giving me access to the myresource resource.
However, when I try a similar flow with a service account (to which I also granted the somerole role)using the client credentials flow to obtain the initial access token:
grant_type=client_credentials&client_id=serviceaccount1&client_secret=77c1ffa8-0ea8-420c-ad45-e1a69a03838d
I am able to obtain an RPT, but that RPT does not contain myresource in the authorization/permission block, only the Default resource.
I have been trying to understand why that is. I have also tried using the .addClient("serviceaccount1") or even .addUser("service-account-serviceaccount1") in the UmaPermissionRepresentation, but still, the policy doesn't seem to kick in and my service account does not have access to the resource.
This is using Keycloak 4.8.0.Final.
Note: using the keycloak admin client, I am able to create policies/permissions that actually make this work; but in my environment this would causes other problems because of the roles I would need to assign to the admin client (like viewing all clients to retrieve an id etc.)

I have the same problem with KeyCloak 11.0.2.
Shared resources do not end up in the permission tickets of service accounts. Service accounts are explicitly excluded in the authorization token service.
Since sharing resources with service accounts is possible, this seems inconsistent.
However, you can work around this by explicitly setting the azp claim to something other than your client_id via a protocol mapper on your client.
.

Related

Microsoft flow:ForbiddenError-403, when trying to create private channel in MS teams

I am trying to make an HTTP request into MS teams in order to create private channel like in the following example.
https://learn.microsoft.com/en-us/graph/api/channel-post?view=graph-rest-1.0&tabs=http
In order to authenticate it, the HTTP request, with option of "Active Directory oauth", it needs some info. 1) Cliend ID, 2) Tenant ID, 3) Audience & 4) Credential Type.
Therefore, I register an app at Registration App Azure page, where I have all this info + create a secret to provide it. In addition I give permissions. My task is to create/delete private channels and add/drop members. Why is there a 403-statusCode error called it "Forbidden"?
Also, in a lot of docs, a token is mentioned, but I donot know how to create&use it, as there is also not an accurate, step-by-step example for all this authentication/authorization/permissions.
Can someone provide that? Or explain why is that error there, as the info microsoft.docs is inefficient?
https://learn.microsoft.com/en-us/graph/resolve-auth-errors
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
https://learn.microsoft.com/en-us/graph/resolve-auth-errors
The 403 error indicates that your token lacks the permission to call the api. Each api document clearly explains what permissions are required to call the api.
Take the create channel as an example: It lists the permissions you need to call the api. These permissions are arranged from small to large, and you only need to select one of them. Then you need to add the permission to your application, and then grant the administrator consent for the permission.
Go to Azure portal>Azure AD>App registrations>your app>API permissions.
What you need to note is that permissions are divided into application permissions and delegated permissions.
Delegated permission is the authorization of the service principal on
behalf of the user. It usually involves user interaction. If you need
to log in to the user, you can choose to grant the permission, and
then you need to use the auth code flow to obtain an access token.
Application permission is the authorization of the service principal
on their own behalf. It is usually used in a daemon where no user is
logged in. If you do not need to log in to the user, you can choose to
grant the permission, and then you need to use the
client credential flow to obtain an access token.

Using Anypoint Access Management - Mulesoft APIs

Good morning I am using internal mulesoft Access Management APIs API Reference. I have successfully setup my postman to get the security token after login, and even executed successfully the /api/users/me. However, regardless of the access provided to the connection/login user, i can't get the full list of users (/api/users), receiving a Not authorized error. Let me explain the context. We are running on a federated platform, so we can't manage the users registration from the console, but need to wait until they login through SSO the first time to grant access to the correspondent business group and role. There is a complain as the users need to send the admin a note letting know of their successful first login, and afterwards wait to receive the access to the business group. After they login for the first time, their profiles are created in the root org. You can see them only when you are in the master organization. However, you can't get their new user id when you request a list of users of this master organization (/api/organizations/{orgId}/users). We are looking to execute this /api/users in a batch app that runs periodically and do a cross verification to get the users not associated to any orgid or role. This way we can avoid the requirement of the user sending a note to the admin. When I execute the /accounts/api/users, (API Call), we receive a 401 Unauthorized response, despite the token is correct as it is working fine with the others APIs. there is no mention of any other parameter or requirement in the API reference.
Please advise what can be done to solve this authorization error and complete our app. Thank you in advance.
Had the same issue but figured it out.
Instead of calling /api/users, you should be calling
https://anypoint.mulesoft.com/accounts/api/organizations/{orgId}/members
to get a list of users

Is AEM authentication Stateless

Is AEM Authentication (closed user group) stateless ? What happens if we have multiple publisher, will the authentication handler ensure the user is authenticated in all the instance of the publisher ?
Could not find a document confirming this, So any help is appreciated.
Thanks.
The default AEM Authentication (CRX Login Module) is not stateless , the authentication is confirmed by a login token. When a user logs in the token information is stored under .tokens node of the corresponding user node (/home/users). The value of the token is also stored in the browser as a cookie login-token. Whenever a request comes in , the cookie value and the token in the repository is compared.[
You can test by deleting the .tokens node and refreshing some page that cannot be accessed by anonymous
]
In a multi publisher environment the token is created only on the instance which logged the user in. Since other instances cannot find the token for the cookie value in their repositories the request will be rejected.
If you enable sticky sessions , all requests by a particular client are always directed to the same instance.
Here's a page on Oak's token module . AEM uses crx token module but how they work is essentially same. Since your credentials are passed to a single instance by a form based authentication handler the token is created only in one instance. The authentication handler page also has some details on the token and the cookie.
UPDATE:
With AEM 6.1 , the authentication can now be made stateless as long as the user exists on all the publish instances. This is done by using a encrypted cookie that can be decrypted by all publish instances when they share the same HMAC key. More information can be found here : https://docs.adobe.com/docs/en/aem/6-1/administer/security/encapsulated-token.html
i think it´s possible if you activate the clustering on your authors, the .token node will be replicated to all instances and while comparing the users token ressource and the cookie the identification succeeds, this is one of the benefits of the jcr philosophy :all is content
Enable encapsulated token option in OSGI. Then it will authenticate seamlessly. But there are 2 prerequisite or conditions to get it worked. One is to put the same HMAC key on all the instances and secondly the user should exist. if these 2 conditions are met then if you login on one stack and the second stack wont required authentication again.

LdapAuthenticationProvider not checking if user is not active

I can auth my website with either ldap or by looking in db using different spring security authentication providers.
When i use the database auth, i use UserDetailsService, which correctly checks if my user is notActive and throws DisabledException correctly.
but using LdapAuthenticationProvider this does not occur. why?
spring security 2.0.1
Which LdapAuthenticator are you using? If you use BindAuthenticator it will bind as the given user, eventually the directory server should reject if the user account disabled/expired.
I haven't used LdapAuthenticationProvider myself, but if its not done automatically you can retrieve the userdetails, The UserDetails class has bunch of methods to check weather the account is enabled/locked/expired.

CAS authentication and limiting access for specified users

I'm using CAS (Central Authentication Service) from Jasig in a client JSF app running on tomcat 6 server. I would like to limit the access to the app just for the users specified in my database rather than all the users which can be authenticated using that CAS service. When the user attempts to log in, I need to check if his username is also in my database's table user and if it is - allow the access to the app. Otherwise, I would like to redirect user to a page "You don't have permission to access this part of the application". So I need authorization as well. Is there a good way to authorize the users in jsf 2.0? Thanks in advance for any help/suggestions.
Sounds like you need to design a custom Authentication Handler class in CAS. In theory, your handler would extend this [1], perform all the necessary checks and database look ups and will then be able to return a signal that indicates whether or not the user could authN.
You should then reference your custom handler in the deploerConfigContext.xml file.
For displaying the message, you could either throw an exception with the proper messages code, such that the message would appear above the login form, or you could alter the spring webflow and generate a new view-state which the user would be redirected to, if they fail to get access. The first approach is much easier to implement.
Another approach would be to take advantage of the isUserInRole() method [2] using the persondir api.
[1] http://developer.jasig.org/projects/cas/cas-server-core/cas-server/cas-server-core/apidocs/org/jasig/cas/authentication/handler/support/AbstractUsernamePasswordAuthenticationHandler.html
[2] https://wiki.jasig.org/pages/viewpage.action?pageId=47874068