[aerogear-dev] Keycloak integration and UPS Sender

Stian Thorgersen stian at redhat.com
Thu Jun 19 04:33:12 EDT 2014


Here's an idea on how it could be done (disclaimer: this is just a rough idea so take it with a pinch of salt ;)). Some benefits:

* Relatively simple to maintain backwards compatibility
* Support public clients directly (by using logged in users permissions)
* One application can access multiple UPS Apps
* No need to maintain master secret in UPS (and can support multiple methods to auth in the future, for example cert or jwt
* Manage access through KC - what app/client or user can access what UPS App


When creating a new UPS App create:

* A role on unified-push-server - the name should be equal to id of UPS app

Applications should have 3 options to authenticate:

* As the logged in user (for client side applications)
* As themselves (for server side applications)
* HTTP Basic

The master secret can also be removed from UPS App as it should no longer be required.

As the logged in user
---------------------
This allows public applications to send push messages on behalf of the logged in user. The steps required are:

1) Create an application/client in Keycloak
    * Set to public client
    * Add scope on UPS App role
2) Create user
    * Add role mapping on UPS App role
3) Users logs in with username/password, social, etc through KC login   
   screens
4) Application can send push messages with bearer token using users    
   permissions

As themselves
-------------
This allows a server-side application to send push messages on behalf of itself. The steps required are:

1) Create an application/client in Keycloak
    * Add scope on UPS App role
2) Create user
    * Add role mapping on UPS App role
    * Set a long unique password (equivalent of master secret)
3) Application logs in with username/password (equal to UPS App
   id/master-secret) using direct grant
4) Application can send push messages with bearer token using its own    
   permissions

In the future Keycloak will support additional mechanism for a server-side application to authenticate on behalf of itself (cert, jwts, etc).

HTTP Basic
----------
For backwards compatibility we can add a valve that extracts the UPS App id and master secret from Basic auth. It will then use the direct grant mechanism to obtain a token from Keycloak. The steps required to configure is the same as "As themselves".



----- Original Message -----
> From: "Bruno Oliveira" <bruno at abstractj.org>
> To: "AeroGear Developer Mailing List" <aerogear-dev at lists.jboss.org>
> Sent: Wednesday, 18 June, 2014 8:12:55 PM
> Subject: Re: [aerogear-dev] Keycloak integration and UPS Sender
> 
> Hi guys, let's see the result of the conversation with KC team and we
> can revisit this discussion if some changed is required.
> 
> On 2014-06-18, Matthias Wessendorf wrote:
> > On Wed, Jun 18, 2014 at 12:12 AM, Bruno Oliveira <bruno at abstractj.org>
> > wrote:
> >
> > > Answers inline.
> > >
> > > On 2014-06-17, Matthias Wessendorf wrote:
> > > > On Tue, Jun 17, 2014 at 8:51 PM, Matthias Wessendorf
> > > > <matzew at apache.org>
> > > > wrote:
> > > >
> > > > >
> > > > >
> > > > >
> > > > > On Tue, Jun 17, 2014 at 7:17 PM, Bruno Oliveira <bruno at abstractj.org>
> > > > > wrote:
> > > > >
> > > > >> Hi Matthias, answer inline.
> > > > >>
> > > > >> On 2014-06-17, Matthias Wessendorf wrote:
> > > > >> > On Tue, Jun 17, 2014 at 4:26 PM, Bruno Oliveira <
> > > bruno at abstractj.org>
> > > > >> wrote:
> > > > >> >
> > > > >> > > Good morning peeps,
> > > > >> > >
> > > > >> > > I have a problem to solve which might affect the Sender and
> > > > >> > > all the related clients.
> > > > >> > >
> > > > >> > > Previously, the UPS Sender was protected by the basic
> > > authentication
> > > > >> > > method[1], so anyone in possession of _PushApplicationID_ and
> > > > >> > > _MasterSecret_ is able to send push messages.
> > > > >> > >
> > > > >> > > After the integration with Keycloak now everything under _/rest_
> > > > >> > > is properly protect by KC which is totally correct. Our sender
> > > > >> > > is
> > > > >> under
> > > > >> > > the same umbrella which means that now Bearer token
> > > authentication is
> > > > >> > > required[2] and Basic authentication won't exist anymore.
> > > > >> > >
> > > > >> >
> > > > >> >
> > > > >> > The device (un)registration endpoints are hit by this as well
> > > > >> > (/rest/registry/device/*).
> > > > >>
> > > > >> Currently Keycloak is protecting our endpoints under /rest/*
> > > > >>
> > > > >> >
> > > > >> > I am wondering if it isn't it possible to keep those URLs
> > > > >> > protected
> > > via
> > > > >> > HTTP_BASIC, or does the keycloak.js usage deny this?
> > > > >>
> > > > >> Is not the Keycloak.js usage responsible for this, but the correct
> > > > >> configuration of the application atm. Please compare:
> > > > >>
> > > > >> - master branch:
> > > > >>
> > > > >>
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/master/server/src/main/webapp/WEB-INF/web.xml#L56
> > > > >> - keycloak.js branch:
> > > > >>
> > > > >>
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/keycloak.js/server/src/main/webapp/WEB-INF/web.xml#L33
> > > > >>
> > > > >> Now we're fully using Keycloak bearer tokens instead of Basic.
> > > > >>
> > > > >
> > > > >
> > > > > Oh, I was following Bill's sample project, where he did not use the
> > > > > 'KEYCLOAK' auth-method:
> > > > >
> > > > >
> > > https://github.com/keycloak/keycloak/blob/master/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/web.xml#L44
> > > > >
> > > > > But we had the exclusion working w/ the KEYCLOAK 'auth-method', but
> > > this
> > > > > goes back to our initial starts in Dec/Jan.
> > > > > Here is a rebased commit based on your initial commit:
> > > > >
> > > > >
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/2aabd073aaaafa79943ea41d2651f6f0c5e4248e/server/src/main/webapp/WEB-INF/web.xml#L42-L53
> > > > >
> > > > >
> > > > >>
> > > > >> >
> > > > >> > On master (plain keycloak; before keycloak.js usage) we are doing
> > > > >> > an
> > > > >> > exclude for those URLs:
> > > > >> >
> > > > >>
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/master/server/src/main/webapp/WEB-INF/web.xml#L46-L52
> > > > >>
> > > > >> I tried to include your exclusions, but that didn't work for me.
> > > > >>
> > > > >> >
> > > > >> >
> > > > >> > IMO if possible, keeping these 'exceptions' (or excludes) under
> > > > >> HTTP_BASIC
> > > > >> > would be the simplest solution, as that means none of our client
> > > SDKs
> > > > >> > (Android, iOS, Cordova, Node.js Sender, Java-Sendet etc) would
> > > require
> > > > >> an
> > > > >> > update.
> > > > >>
> > > > >> I had a chat with Stian and looks like it's possible to support both
> > > > >> auth methods in a single app, but that would involve changes on
> > > Keycloak.
> > > > >> It's just the matter of discuss with KC team.
> > > > >>
> > > > >
> > > > > I don't think we need to enable to <auth-method> settings in our
> > > web.xml;
> > > > >
> > >
> > > How do you manage login/logout/current logged in user on Angular.js? Is
> > > possible to do on the server side, but how do you control it on the
> > > client side?
> > >
> >
> > Sure, to protect the admin-ui and most of the /rest/* endpoints we need the
> > one <auth-method>KEYCLOAK</auth-method>. No question there. I was trying to
> > say we do not need multiple 'auth-method' elements on web.xml
> >
> > But I think it should be possible to exclude a few URLs, like '/rest/foo'
> > and '/rest/bar', so that they are completely unprotected in terms of
> > Keycloak (e.g. via different security-constraint elements):
> > https://github.com/aerogear/aerogear-unifiedpush-server/blob/2aabd073aaaafa79943ea41d2651f6f0c5e4248e/server/src/main/webapp/WEB-INF/web.xml
> >
> > In terms of "current logged in user on Angular.js":
> > * For the "/rest/sender" and "/rest/device/registration" endpoints, I don't
> > see a relationship to the user on Angular.js/AdminUI at all.
> >
> > Internally these 'unprotected' (or excluded) endpoints implement the
> > HTTP_BASIC scheme themselves:
> > * They treat the Application/Variant like a 'user', by performing a DB
> > lookup of the give application/variantID
> > * If that (Application or Variant) is found, the endpoints compare the
> > given 'password' form the request w/ the "secret" on the  Application or
> > Variant
> >
> > But for these endpoints (sender and device-registration) there is no real
> > user here like "Mr. Jay" or "Push-Admin Foo".
> >
> > The client (registration or sender SDK) performs the auth, by applying the
> > ID and the secret:
> > curl -3 -u "{PushApplicationID}:{MasterSecret}" .... https://server
> >
> >
> >
> > >
> > > >
> > > > I mean: I think there is no need to enable multiple <auth-method> args,
> > > as
> > > > we had the exclusion already working at some point, using their
> > > > KEYCLOAK
> > > > auth-method
> > >
> > > Stian did that inclusion which for me looks correct. An excerpt from KC
> > > documentation:
> > >
> > > "To be able to secure WAR apps deployed on JBoss AS 7.1.1, JBoss EAP 6.x,
> > > or Wildfly, you must install and configure the Keycloak Subsystem. You
> > > then have two options to secure your WARs. You can provide a keycloak
> > > config file in your WAR and change the auth-method to KEYCLOAK within
> > > web.xml. Alternatively, you don't have to crack open your WARs at all
> > > and can apply Keycloak via the Keycloak Subsystem configuration in
> > > standalone.xml. Both methods are described in this section."
> > >
> > > You can also stick with BASIC, but probably you end with implementations
> > > and customizations that don't take any benefit of Keycloak.js.
> > >
> > > Either way I will talk tomorrow with Stian and let's see what we can do.
> > >
> > > >
> > > >
> > > >
> > > > >
> > > > > My initial hope was to be able to simply exclude a few URLs from the
> > > > > overall Keycloak protection, like the above referenced commit:
> > > > >
> > > > >
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/2aabd073aaaafa79943ea41d2651f6f0c5e4248e/server/src/main/webapp/WEB-INF/web.xml#L42-L53
> > > > >
> > > > > That would be best as that would mean no API change at all, and our
> > > > > client-registration and sender SDKs could stay as they are.
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >>
> > > > >> My two cents is the fact that we should use bearer tokens only,
> > > instead
> > > > >> of mix both auth methods in a single app — now that we have KC.
> > > > >> And discuss the changes into our clients rather sooner than later.
> > > > >>
> > > > >> But I'm open for whatever you guys think it's the best.
> > > > >>
> > > > >>
> > > > >> >
> > > > >> > -Matthias
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> > >
> > > > >> > > The consequence of this is the basic form being presented when
> > > you try
> > > > >> > > to send push notifications[3]. The problem didn't occur before,
> > > > >> because
> > > > >> > > we were just using Basic authentication[4] instead of Bearer
> > > tokens.
> > > > >> > >
> > > > >> > > Possible solutions:
> > > > >> > >
> > > > >> > > 1- After the removal of Basic authentication, move
> > > _PushApplicationID_
> > > > >> > > and _MasterSecret to http headers like:
> > > > >> > >
> > > > >> > > -H "PushApplicationID: XXXXXX" -H "MasterSecret: 42"
> > > > >> > >
> > > > >> > > IMO it sounds correct and reasonable for me.
> > > > >> > >
> > > > >> > > 2. Create a role specific for the sender like
> > > > >> > > _push-applications_
> > > and
> > > > >> > > dinamically add _PushApplicationID_ and _MasterSecret on
> > > > >> > > Keycloak
> > > > >> where:
> > > > >> > >
> > > > >> > > username: _PushApplicationID_
> > > > >> > > password: _MasterSecret_
> > > > >> > >
> > > > >> > > The implications of this alternative is the fact of have to
> > > > >> > > manage
> > > > >> those
> > > > >> > > credentials on the server side inclusion/exclusion/login
> > > > >> > >
> > > > >> > > 3. Implement another authentication provider specifically for
> > > > >> > > the
> > > > >> sender
> > > > >> > > and Basic authentication[5]
> > > > >> > >
> > > > >> > > 4. Do nothing. The consequences of this alternative is to
> > > implement
> > > > >> > > everything already done by Keycloak.js and manage session tokens
> > > by
> > > > >> hand
> > > > >> > > on the admin-ui.
> > > > >> > >
> > > > >> > > To me the first alternative seems to be more simple, but I
> > > > >> > > really
> > > want
> > > > >> > > your feedback on it, once it affects the whole project.
> > > > >> > >
> > > > >> > > [1] -
> > > > >> > >
> > > > >> > >
> > > > >>
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/6c1a0d3fedea8fb6ba918009fd8e9785779c151f/jaxrs/src/main/java/org/jboss/aerogear/unifiedpush/rest/sender/PushNotificationSenderEndpoint.java#L56
> > > > >> > >
> > > > >> > > [2] -
> > > > >> > >
> > > > >>
> > > https://github.com/abstractj/aerogear-unifiedpush-server/tree/keycloak.js
> > > > >> > > [3] -
> > > > >> > >
> > > > >> > >
> > > > >>
> > > http://photon.abstractj.org/AeroGear_UnifiedPush_Server_2014-06-17_10-00-09_2014-06-17_10-00-12.jpg
> > > > >> > >
> > > > >> > > [4] -
> > > > >> > >
> > > > >> > >
> > > > >>
> > > https://github.com/aerogear/aerogear-unifiedpush-server/blob/master/server/src/main/webapp/WEB-INF/web.xml#L57
> > > > >> > >
> > > > >> > > [5] -
> > > > >> > >
> > > > >>
> > > https://github.com/keycloak/keycloak/tree/master/examples/providers/authentication-properties
> > > > >> > >
> > > > >> > > --
> > > > >> > >
> > > > >> > > abstractj
> > > > >> > > _______________________________________________
> > > > >> > > aerogear-dev mailing list
> > > > >> > > aerogear-dev at lists.jboss.org
> > > > >> > > https://lists.jboss.org/mailman/listinfo/aerogear-dev
> > > > >> > >
> > > > >> >
> > > > >> >
> > > > >> >
> > > > >> > --
> > > > >> > Matthias Wessendorf
> > > > >> >
> > > > >> > blog: http://matthiaswessendorf.wordpress.com/
> > > > >> > sessions: http://www.slideshare.net/mwessendorf
> > > > >> > twitter: http://twitter.com/mwessendorf
> > > > >>
> > > > >> > _______________________________________________
> > > > >> > aerogear-dev mailing list
> > > > >> > aerogear-dev at lists.jboss.org
> > > > >> > https://lists.jboss.org/mailman/listinfo/aerogear-dev
> > > > >>
> > > > >>
> > > > >> --
> > > > >>
> > > > >> abstractj
> > > > >> _______________________________________________
> > > > >> aerogear-dev mailing list
> > > > >> aerogear-dev at lists.jboss.org
> > > > >> https://lists.jboss.org/mailman/listinfo/aerogear-dev
> > > > >>
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Matthias Wessendorf
> > > > >
> > > > > blog: http://matthiaswessendorf.wordpress.com/
> > > > > sessions: http://www.slideshare.net/mwessendorf
> > > > > twitter: http://twitter.com/mwessendorf
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > Matthias Wessendorf
> > > >
> > > > blog: http://matthiaswessendorf.wordpress.com/
> > > > sessions: http://www.slideshare.net/mwessendorf
> > > > twitter: http://twitter.com/mwessendorf
> > >
> > > > _______________________________________________
> > > > aerogear-dev mailing list
> > > > aerogear-dev at lists.jboss.org
> > > > https://lists.jboss.org/mailman/listinfo/aerogear-dev
> > >
> > >
> > > --
> > >
> > > abstractj
> > > _______________________________________________
> > > aerogear-dev mailing list
> > > aerogear-dev at lists.jboss.org
> > > https://lists.jboss.org/mailman/listinfo/aerogear-dev
> > >
> >
> >
> >
> > --
> > Matthias Wessendorf
> >
> > blog: http://matthiaswessendorf.wordpress.com/
> > sessions: http://www.slideshare.net/mwessendorf
> > twitter: http://twitter.com/mwessendorf
> 
> > _______________________________________________
> > aerogear-dev mailing list
> > aerogear-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/aerogear-dev
> 
> 
> --
> 
> abstractj
> _______________________________________________
> aerogear-dev mailing list
> aerogear-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/aerogear-dev



More information about the aerogear-dev mailing list