On 12/13/2016 11:35:49 AM, Richard van Duijn <rjvduijn(a)gmail.com> wrote:
Ok, thanks. That did the trick. I was under de assumption that if left blank, the
policy-enforcer would be correctly configured from keycloak itself. But I now understand
we need to specify more specific resource actions in this keycloak.json file.
Pedro Igor: When left blank, the enforcer loads all resources from the server and perform
access decisions based on the path you defined for each of them. That means you must have
a resource with /api/resource URL if your application is serving any request at that path
(or pattern). For REST APIs, you usually want to have your paths configured in
keycloak.json in order to define which scopes are associated with a given HTTP method.
Other quick question:
Why is it that when fetching all entitlements from the frontend javascript with the call:
this.authorization.entitlement('photoz-restful-api').then(function(rpt) {
console.log('Entitlements loaded...%o', JSON.stringify(jwt_decode(rpt), null,
' '));
});
Succeeds, and doing the same call from the backend using the configred Authz client as in
the AuthorizationClientExample.java I get an Bad Request response from keycloak.
private static void obtainAllEntitlements() {
// create a new instance based on the configuration defined in keycloak-authz.json
AuthzClient authzClient = AuthzClient.create();
// obtian a Entitlement API Token in order to get access to the Entitlement API.
// this token is just an access token issued to a client on behalf of an user with a scope
kc_entitlement
String eat = getEntitlementAPIToken(authzClient);
// send the entitlement request to the server in order to obtain a RPT with all
permissions granted to the user
EntitlementResponse response =
authzClient.entitlement(eat).getAll("hello-world-authz-service");
String rpt = response.getRpt();
System.out.println("You got a RPT: " + rpt);
// now you can use the RPT to access protected resources on the resource server
}
Is this configuration as well?
Pedro Igor: It should be a configuration issue. You may check:
1) Your client credentials are correct
2) Check if your client is configured to allow "Direct Grant" and user's
credentials are correct
3) Your client is allowed to obtain a token with the uma_authorization scope (check if
your client is configured with "Consent Required")
Regarding #2, you are not required to enable Direct Grant to obtain RPTs from the server.
This example uses direct grant for demonstration purposes.
Thanks!
Op di 13 dec. 2016 om 14:17 schreef Pedro Igor <psilva(a)redhat.com
[mailto:psilva@redhat.com]>:
It could be related with your policy-enforcer config in keycloak.json. There you can
associate a scope with a specific HTTP method for a given path, maybe this is causing the
401.
If you have everything set correctly, the only thing we can do is debug and check what is
happening. I don't think this smells like a bug because the same scenario works with
our tests + photoz app example. But better debug your play adapter and see what may be
causing this, to make sure.
On 12/13/2016 10:35:21 AM, Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]> wrote:
Thank you for clarifying that! Much appreciated!
I'm progressing with my adapter. Using the Photoz example I can login and authorize
requests going to the photoz-restfull-api (which in my case is my play application).
But one resource refuses to load for non-admin users. Namely the /album/create resource
returns an Unauthorized. I will try to elaborate on what I am currently doing. Hopefully
someone can point me the error.
* The javascript frontend application calls the /photoz-rest-api/album/create resource
using a post with the bearerToken received from the login.
* Then my PlayFramework controller Action is intercepted and the bearerToken is verified
using the: AdapterRSATokenVerifier.verifyToken() method.
* If succceful the KeycloakAdapterPolicyEnforcer is used to authorize my request using the
photoz policies.
* This returns 401 in case of the user Alice, and is accepted in case of Admin.
What I do no understand is that the Policy Evaluator in the admin console results in a
PERMIT in case of Alice accessing the album resource with scope 'Create'. But the
KeycloakAdapterPolicyEnforcer tells Alice is Unauthorized. Am I missing a vital point in
the process?
The entitlements I have for Alice are the following (which clearly states the user is
allowed to create on the album resource):
{
"jti": "6fa19f41-f720-4285-965f-e4373544346c",
"exp": 1481632355,
"nbf": 0,
"iat": 1481632055,
"iss": "http://127.0.0.1:8080/auth/realms/photoz
[
http://127.0.0.1:8080/auth/realms/photoz]",
"aud": "photoz-html5-client",
"sub": "85e9868e-262e-4290-8a23-93f8392cffd7",
"typ": "Bearer",
"azp": "photoz-html5-client",
"nonce": "55b16f6b-5af9-40de-871e-ab8712bd1f57",
"auth_time": 1481631352,
"session_state": "73453cd9-01df-4124-a9ca-585352c0e040",
"name": "Alice In Chains",
"given_name": "Alice",
"family_name": "In Chains",
"preferred_username": "alice",
"email": "alice(a)keycloak.org [mailto:alice@keycloak.org]",
"acr": "0",
"client_session": "2e16eade-c3a2-40ae-b766-3bac6b89d4d4",
"allowed-origins": [
"*"
],
"realm_access": {
"roles": [
"uma_authorization",
"user"
]
},
"resource_access": {
"photoz-restful-api": {
"roles": [
"manage-albums"
]
}
},
"authorization": {
"permissions": [
{
"scopes": [
"urn:photoz.com:scopes:album:view",
"urn:photoz.com:scopes:album:create"
],
"resource_set_id": "71996b0c-48c1-44c9-8fda-d0ba46b451b7",
"resource_set_name": "Album Resource"
},
{
"scopes": [
"urn:photoz.com:scopes:profile:view"
],
"resource_set_id": "0236b990-40dd-4bf3-9a49-25bc3bc6273c",
"resource_set_name": "User Profile Resource"
}
]
}
}
/Richard
Op do 8 dec. 2016 om 21:11 schreef Pedro Igor <psilva(a)redhat.com
[mailto:psilva@redhat.com]>:
Yeah, I missed that part too :)
Clients marked as bearer-only are not allowed to access the token endpoint. However, you
can still use bearer-only in your keycloak.json (adapter config) to indicate that only
requests with a bearer token are allowed to access your resource server (backend-client).
Regards.
Pedro Igor
On 12/8/2016 5:46:25 PM, Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]> wrote:
Pedro,
I've imported the json file myself and I was able to fetch the AT with postman and
things work now. The only difference I see in the server configuration is that I had
confired the backend-client with Access-Type 'Bearer-only', which (after the
import) is now 'Confidential'..
In my perception i had to configure the backend-client with a bearer-only access-type as
it does do any logins just as the 'bearer-only:true' flag in the adapter config
json.
Am I mistaken here?
Well at least I can continue now. but still this seems a bit odd to me.
Thank you again for your great help! It is much appreciated!
/Richard
Op do 8 dec. 2016 om 13:49 schreef Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]>:
You've got me confused as well.. haha
No I'm not reaching the lines using the policyEnforcer. The error occurs earlier in
the process.
Could you perhaps explain what you send in the postman request.
What is put in it the request is the following:
requestHeaders.put("Authorization",
BasicAuthHelper.createHeader(Configuration.this.clientId, secret));
with the clientId being: backend-client and the secret being:
6ce718ad-2ab1-42ff-bf01-35a03eab3aee
resulting in the header: Authorization : Basic
YmFja2VuZC1jbGllbnQ6NmNlNzE4YWQtMmFiMS00MmZmLWJmMDEtMzVhMDNlYWIzYWVl
Other than that I do not have any clues what is wrong.
The AT request is generated during startup of my backend server. So I do not yet have any
frontend rest calls containing a bearerToken comming in.
My assumption is that I can initialize the keycloakDeployment once for my entire
application and then use it for each call comming in. Am I correct?
My guess now is that this assumption is wrong.
/Richard
Op do 8 dec. 2016 om 13:05 schreef Pedro Igor <psilva(a)redhat.com
[mailto:psilva@redhat.com]>:
On 12/8/2016 7:06:44 AM, Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]> wrote:
Hi Pedro,
Thank you for the reply.
Fist I'll answer your questions, then I'll clarify my setup a bit more. Please
find attached my realm config file as well.
* The realm name was a typo. In the meantime I've reconfigured my realm to ensure the
'.' char was not messing up. Turned out not to be the case.
* I'm not able to retrieve an AT from keycloak for the backend-client (which is set to
bearer-only). With the given Postman request I just get the 400 bad request error and
accompanying message.
Pedro Igor: I was able to get an AT after importing your realm and sending the same
postman request. Now I'm confused :) The client is backend-client, correct ?
* I've followed the getting started guid up to securing the jboss servlet. I've
stopped there as I wanted to use a keycloak distribution in combination with a
PlayFramework application (for which there is no adapter available yet).
I've followed the steps from this
[
http://bandrzejczak.com/blog/2015/11/22/single-sign-on-with-keycloak-in-a...
to get the bearerToken approach working. Using the AdapterRSATokenVerifier class I was
able to verify the bearerToken received from the javascript frontend. What I basically
have is a filter that intercepts the frontend requests, picks up the bearerToken and
checks it's validity. If valid the resource is accessible otherwise the user receives
an error.
The next step was to include policies in the setup. Setting up the adapter for the
playFramework was a bit difficult as there is no real documentation on that subject, only
example implementations like the ones for spring security and jetty. But before getting to
the complex logic I've added the policy-enforcer: {} line in the keycloak.json config
file for the backend-client. This json is then loaded and used in
KeycloakDeploymentBuilder.build(keycloakConfig). This is the point where it fails, as the
config contains the policy-enforcer line, the PolicyEnforcer class is initialized, which
in turn attempts to retrieve the AT from keycloak.
Is there some flaw in my reasoning?
* The javascript frontend authenticates itself using the keycloak.js adapter. It adds the
accessToken to the Authorization header for the rest-client to pickup
* The rest client (my backend-client) verifies the bearerToken using the
AdapterRSATokenVerifier
* Then the rest client checks the authorization using the folliwing lines of code:
final PolicyEnforcer policyEnforcer = keycloakDeployment.getPolicyEnforcer();
BearerTokenPolicyEnforcer bearerTokenPolicyEnforcer = new
BearerTokenPolicyEnforcer(policyEnforcer);
final AuthorizationContext authorizationContext =
bearerTokenPolicyEnforcer.authorize(facade);
Pedro Igor: It looks correct. Although it seems you are not even reaching the line above
where permissions are actually enforced. Besides, make sure you have all bearer token
validations in place based on other adapters we have.
You are almost there. You just need to figure out why you can't obtain an AT from the
server even if using postman, curl, etc. I think that if you solve this, you will get
everything working (or hit some new issue after this one :)).
Hope this clarifies it a bit. I've attached my realm configuration json file. By the
way I'm using keycloak 2.4.0-Final.
Many many thanks for your help!
If this approach is valid I'm hapy to contribute my code to the community for others
to work with.
/Richard
Op do 8 dec. 2016 om 01:13 schreef Pedro Igor <psilva(a)redhat.com
[mailto:psilva@redhat.com]>:
Hi Richard,
In your first message, it seems the token endpoint
is http://127.0.0.1:8080/auth/realms/local.development/protocol/openid-connect/token.Here
[
http://127.0.0.1:8080/auth/realms/local.development/protocol/openid-conne...
are using a realm "local.development".
In your last message with the postman request, you are using a token endpoint like
this /auth/realms/development/protocol/openid-connect/token. Where the realm is
"development", the same you have used in keycloak.json.
Would that be a misconfiguration or just a typo ?
Besides, what happens when you send that postman request to the server ? Are you able to
get a AT ?
This is pretty much what the enforcer does during initialization, obtain a AT before
querying the Protection API for protected resources. And is what your stack trace shows.
If you are not able to obtain a token using the postman request, it probably means you
have something wrong with your realm/client configuration on the server.
Last question, are you able to run any of our authorization examples ? Or even
successfully follow our Getting Started guide ?
Thanks.
Pedro Igor
On 12/7/2016 12:05:10 PM, Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]> wrote:
Forgot to include the postman request.. here it is:
POST /auth/realms/development/protocol/openid-connect/token HTTP/1.1
Host: 127.0.0.1:8080 [
http://127.0.0.1:8080]
Authorization: Basic YmFja2VuZC1jbGllbnQ6NmNlNzE4YWQtMmFiMS00MmZmLWJmMDEtMzVhMDNlYWIzYWVl
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
/Richard
Op wo 7 dec. 2016 om 15:00 schreef Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]>:
Somehow I do not get any logs in keycloak server.log. I've attempted to change the
loglevel in standalone.xml to TRACE, but to no avail. Maybe you can give me a pointer to
which logger I should change to see the correct logs show up.
Besides that I've done some debugging using Postman as well. Using the following
request I get the message:
{
"error": "invalid_client",
"error_description": "Bearer-only not allowed"
}
This is weird to me as the keycloak.json file states that I am connecting to a bearer-only
client.
Hope this helps to clarify it for you.
My keycloak.json configuration file looks like this:
{
"realm": "development",
"bearer-only": true,
"auth-server-url": "http://127.0.0.1:8080/auth
[
http://127.0.0.1:8080/auth]",
"ssl-required": "external",
"resource": "backend-client",
"use-resource-role-mappings": true,
"credentials": {
"secret": "SECRETHERE"
},
"policy-enforcer": {}
}
Hope this helps to clarify some of your questions.
/Richard
Op wo 7 dec. 2016 om 12:47 schreef Pedro Igor <psilva(a)redhat.com
[mailto:psilva@redhat.com]>:
Do you get anything in server logs ? It may be related with invalid client credentials.
On 12/6/2016 12:41:38 PM, Richard van Duijn <rjvduijn(a)gmail.com
[mailto:rjvduijn@gmail.com]> wrote:
I'm creating a POC application using playframework and angular. The
frontend will be protected using the keycloak javascript adapter and the
backend rest services will be a bearer-only application.
Without the policies turned on in the keycloak.json everything goes well.
But when I turn the policies by adding "policy-enforcer": { } on for the
rest services, I get an 400 Bad Request response from the Keycloak server
during initialization.
After some debugging I noticed it had to do with the initialization of the
PolicyEnforcer which attempts to call the following server keycloak
endpoint:
http://127.0.0.1:8080/auth/realms/local.development/protocol/openid-conne...
[
http://127.0.0.1:8080/auth/realms/local.development/protocol/openid-conne...]
Below you will find the stacktrace and request and response objects.
Hope someone can point me in the right direction. For instance how to
configure keycloak logging to get some more details on what the reason for
the 400 bad request is.
Many many thanks!
/Richard
*Stacktrace*:
at
org.keycloak.authorization.client.util.HttpMethod.execute(HttpMethod.java:92)
at
org.keycloak.authorization.client.util.HttpMethodResponse$2.execute(HttpMethodResponse.java:48)
at
org.keycloak.authorization.client.AuthzClient.obtainAccessToken(AuthzClient.java:112)
at
org.keycloak.authorization.client.AuthzClient.protection(AuthzClient.java:91)
at
org.keycloak.adapters.authorization.PolicyEnforcer.(PolicyEnforcer.java:57)
at
org.keycloak.adapters.KeycloakDeploymentBuilder.internalBuild(KeycloakDeploymentBuilder.java:126)
at
org.keycloak.adapters.KeycloakDeploymentBuilder.build(KeycloakDeploymentBuilder.java:135)
at
security.KeycloakSecurityModule.configure(KeycloakSecurityModule.java:53)
at com.google.inject.AbstractModule.configure(AbstractModule.java:62)
... many google guice calls ...
at
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:129)
at
play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:121)
*Request object*:
builder = {RequestBuilder@12557}
method = "POST"
charset = {UTF_8@12563} "UTF-8"
version = null
uri = {URI@12564} "
http://127.0.0.1:8080/auth/realms/local.development/protocol/openid-conne...
[
http://127.0.0.1:8080/auth/realms/local.development/protocol/openid-conne...]
"
headergroup = {HeaderGroup@12565} "[Authorization: Basic
YmFja2VuZC1jbGllbnQ6NmNlNzE4YWQtMmFiMS00MmZmLWJmMDEtMzVhMDNlYWIzYWVl]"
entity = null
parameters = {LinkedList@12566} size = 1
0 = {BasicNameValuePair@12576} "grant_type=client_credentials"
config = null
*Response object*:
HTTP/1.1 400 Bad Request [Connection: keep-alive, X-Powered-By: Undertow/1,
Server: WildFly/10, Content-Type: application/json, Content-Length: 72,
Date: Tue, 06 Dec 2016 12:24:28 GMT]
org.apache.http.conn.BasicManagedEntity@1f8d1780
response = {$Proxy16@12554} "HTTP/1.1 400 Bad Request [Connection:
keep-alive, X-Powered-By: Undertow/1, Server: WildFly/10, Content-Type:
application/json, Content-Length: 72, Date: Tue, 06 Dec 2016 12:24:28 GMT]
org.apache.http.conn.BasicManagedEntity@1f8d1780"
h = {CloseableHttpResponseProxy@12583}
original = {BasicHttpResponse@12584} "HTTP/1.1 400 Bad Request
[Connection: keep-alive, X-Powered-By: Undertow/1, Server: WildFly/10,
Content-Type: application/json, Content-Length: 72, Date: Tue, 06 Dec 2016
12:24:28 GMT] org.apache.http.conn.BasicManagedEntity@1f8d1780"
statusline = {BasicStatusLine@12556} "HTTP/1.1 400 Bad Request"
ver = {HttpVersion@12586} "HTTP/1.1"
code = 400
reasonPhrase = "Bad Request"
entity = {BasicManagedEntity@12555}
reasonCatalog = {EnglishReasonPhraseCatalog@12588}
locale = {Locale@12589} "en_US"
headergroup = {HeaderGroup@12590} "[Connection: keep-alive,
X-Powered-By: Undertow/1, Server: WildFly/10, Content-Type:
application/json, Content-Length: 72, Date: Tue, 06 Dec 2016 12:24:28 GMT]"
params = {ClientParamsStack@12591}
_______________________________________________
keycloak-user mailing list
keycloak-user(a)lists.jboss.org [mailto:keycloak-user@lists.jboss.org]
https://lists.jboss.org/mailman/listinfo/keycloak-user
[
https://lists.jboss.org/mailman/listinfo/keycloak-user]