Thanks!
On Thu, Jan 31, 2019 at 10:26 AM Marek Posolda <mposolda(a)redhat.com> wrote:
Cool, so I created:
https://issues.jboss.org/browse/KEYCLOAK-9468 - Improve keycloak-authz.js
to automatically exchange UMA tickets and refresh tokens
https://issues.jboss.org/browse/KEYCLOAK-9469 - Improve authorization
java client to support automatically exchange UMA tickets and refresh RPT
tokens
Already created yesterday for a bug in quickstarts (cased by expired RPT):
https://issues.jboss.org/browse/KEYCLOAK-9464 app-authz-uma-photoz
quickstart doesn't handle expired RPT
Marek
On 30/01/2019 21:40, Pedro Igor Silva wrote:
+1 for keycloak-authz.js related changes.
Regarding the java adapter, I think we could leverage our
java authz client for that. So, +1 for a JIRA.
On Wed, Jan 30, 2019 at 6:23 PM Marek Posolda <mposolda(a)redhat.com> wrote:
> On 30/01/2019 12:29, Pedro Igor Silva wrote:
>
> Thanks for the feedback, Marek. Kudos to you too for talking about this
> stuff.
>
> Answers inline.
>
> On Wed, Jan 30, 2019 at 8:39 AM Marek Posolda <mposolda(a)redhat.com>
> wrote:
>
>> I recently have a chance to play a bit more with authz services when
>> preparing for the devconf demo. Great stuff and cudos to Pedro and all
>> the others who contributed to authorization services!
>>
>> I just have few questions and possible suggestions to improve in the
>> future :) Also based on some questions and discussion I had after the
>> talk:
>>
>> - My REST service was SpringBoot based and protected by policy enforced
>> configured in the applications.properties like this
>>
>>
https://github.com/mposolda/devconf2019-authz/blob/master/devconf2019-ser...
>> . However I was stuck when I wanted to enable UserManagedAccess for my
>> service. The PolicyEnforcerConfig.UserManagedAccessConfig is an empty
>> class and I couldn't figure how to properly add it in the
>> application.properties file. I've tried to add various things in
>> application.properties like this, but none of them helped:
>>
>> keycloak.policy-enforcer-config.user-managed-access
>> keycloak.policy-enforcer-config.user-managed-access=
>> keycloak.policy-enforcer-config.user-managed-access= (Just left single
>> space here after equals character)
>
>
>> As a workaround, I ended with having separate bean to do it
>> programatically -
>>
>>
https://github.com/mposolda/devconf2019-authz/blob/master/devconf2019-ser...
>> . Is it a bug or is it just me doing something stupid?
>>
>
> He had some feedback in the past about that too, but the workaround you
> did is what people are doing. I've created
>
https://issues.jboss.org/browse/KEYCLOAK-9458.
>
> Similar issue we have when you just want to enable the policy-enforcer
> without any configuration. You need to specify at least one property of
> policy-enforcer (or create a bean).
>
>
>>
>>
>> - I wonder about possible improvements of keycloak-authz.js and if
>> usability can be a bit improved? More specifically I mean this:
>> -- Handling of the 401 response with UMA ticket from resource-server -
>> Can this be done "automatically"? I meant the flow described here:
>>
>>
https://www.keycloak.org/docs/latest/authorization_services/index.html#ha...
>> . Maybe the keycloak-authz itself can just handle the response from
>> resource server, then send the AuthorizationRequest to KC with the UMA
>> ticket and then possibly re-send the request to resource-server with new
>> RPT and do this "automatically" without a need to manually handle it
by
>> the application like this:
>>
>>
https://github.com/keycloak/keycloak-quickstarts/blob/latest/app-authz-um...
>> . WDYT?
>>
>
> We had that before, but due to some changes in UMA specs, I decided to
> remove this capability from the adapter. We can discuss to get it back
> again.
>
> I was thinking that adapter can provide some utility, which will provide
> refreshing of RPT tokens (in case they are expired) and also exchanging UMA
> tickets, which were returned from resource-server for new RPT.
>
> For example adapter can have some utility like "rptProvider", which will
> do something like this (it will be better to have proper state diagram, but
> hopefully you won't be lost in those conditions. Imagine that from the
> point 1, you can go to 1.1 or 1.2):
>
> 1) check if there is existing RPT stored. If yes, it will:
> 1.1) Check if existing RPT is expired. If yes, it will:
> 1.1.1) try to refresh RPT. If refresh success, then adapter will store
> refreshed RPT and go to (1.2)
> 1.1.2) If refresh fails, adapter will delete the existing RPT and go to
> step 2
> 1.2) If existing RPT is not expired, adapter will just call that
> particular "onSuccess" callback method with the RPT
> 2) If there is no RPT, adapter will use it's accessToken to call
> authorization API
> 2.1) If calling authorization API fails, there should be "onAuthzError"
> callback called with the error message sent to it as argument (For example
> "request_submitted", so that caller is aware that request was saved on KC
> side to be approved by the resource owner)
> 2.2) If calling authorization API succeeds, we will store RPT and go to
> (1.2)
>
> --- The "onSuccess" callback will usually invoke the REST service with
> RPT, but service can return UMA ticket in case that RPT is missing some
> permissions. In that case, it should call some builtin function provided by
> the authz client, which will:
> 3) Try to "parse" the UMA ticket from the response.
> 3.1) If it's not there, we need to call some "onOtherError" callback
> method
> 3.2) If it's there, we will use that UMA ticket to call authorization API
> - hence go again to step 2
>
>
> Some pseudo-code how the usage of it can look like:
>
> var rptProvider = keycloakAuthzClient.getRptProvider();
>
> // This is the maximum timeout allowed before "rpt" needs to be refreshed
> rptProvider.setTokenMinimumTimeToLive(10);
>
> // The "rpt" is guaranteed to NOT be expired. However it may not contain
> permissions needed to invoke resource-server
> rptProvider.onSuccess = function(rpt) {
> // Just call the REST service
> var url = 'http://localhost:8080/resource-server';
>
> var req = new XMLHttpRequest();
> req.open('GET', url, true);
> req.setRequestHeader('Accept', 'application/json');
> req.setRequestHeader('Authorization', 'Bearer ' + rpt);
>
> req.onreadystatechange = function () {
> if (req.readyState == 4) {
> if (req.status == 200) {
> alert('Success');
> } else if (req.status == 401) {
> // We MAY have UMA ticket in the response. Let's just
> call "rptProvider.setUmaResponse" and then re-call "run" .
> // Internally, the adapter will try to parse UMA ticket
> from the response and exchange this UMA ticket for the RPT from KC server
> rptProvider.setUmaResponse(req);
> rptProvider.run();
> }
> }
> }
>
> req.send();
>
> });
>
> // This callback is called when the call to KC authorization API failed.
> // The authzError can be for example "request_submitted", so the caller
> is aware that request was created on Keycloak side and needs to be approved
> by the resource owner
> rptProvider.onAuthzError(function(authzError) {
>
> });
>
> // This callback is called on any other error. For example when
> resource-server returns some other error response than "401" with UMA
ticket
> rptProvider.onOtherError(function(errorDetails) {
>
> });
>
> // This will trigger the described flow
> rptProvider.run();
>
>
>
>
>>
>> -- Another thing is refreshing of RPT. It looks that RPT response
>> contains the refresh token, so refreshing of RPTs is possible. However
>> the keycloak-authz.js client doesn't have any support for automatically
>> refreshing RPT token. I mean something similar, which is provided by
>> keycloak.js itself (method "keycloak.updateToken" which automatically
>> refreshes the token if needed). Due this limitation, it seems there is a
>> bug in our quickstart. When you try the quickstart
>> "app-authz-uma-photoz" and you go through the flow like this:
>> - Open
http://localhost:8080/photoz-html5-client and login as jdoe
>> - Create some album
>> - Wait 10 minutes (RPT expiration is same like AccessTokenLifespan, so 5
>> minutes by default)
>> - Try to create some album again - now fails with 403 due the RPT
>> expired and no support for refreshing it in the keycloak-authz.js or the
>> application itself.
>> Should I create JIRA for this?
>>
>
> Yes, please.
>
> Created
https://issues.jboss.org/browse/KEYCLOAK-9464
>
>
>
>>
>>
>> - It seems we don't have any Java based adapter for the frontend clients
>> written in Java? We have Java based authorization client, but that
>> provides just sending REST requests. It doesn't provide things like I
>> mentioned above though (Storing RPT, automatically refreshing RPT,
>> Automatically handling 401 response with the UMA ticket from
>> resource-server and sending the request to KC etc). Any plan to have
>> this?
>>
>
> Could we leverage the authz client for that ? If you could create a JIRA
> with more details about the scenarios we are trying to support, we can
> start thinking about a solution.
>
> I was thinking about something quite similar like the javascript client
> (keycloak-authz.js) will provide. If we agree on the javascript client,
> hopefully java can have something similar.
>
> Marek
>
>
> Thanks !
>
>
>>
>> Marek
>>
>> _______________________________________________
>> keycloak-dev mailing list
>> keycloak-dev(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
>>
>
>