[keycloak-user] Get magic link for users to login

Ulrik Lejon ulrik.lejon at mollyware.se
Mon Apr 24 09:30:46 EDT 2017


Hi,

Thank you for providing this example!
The problem I'm having now is how to provide the frontend application with
the OAuth 2 bearer token? Is it possible to generate a token on behalf of
the user without knowing the user's password?

The flow right now is like this:

1. User makes a request to my custom keycloak rest endpoint to get the
magic link
2. User paste the link in the browser
3. My custom keycloak authenticator, which is first in the browser flow
chain, marks the AuthenticationFlowContext as successfull and sets the user
property.
4. User is redirected to my frontend app

To be able to continue the flow I need to obtain a OAuth2 bearer token that
I can use in each request to my backend application. Is there a way of
doing that?


ons 19 apr. 2017 kl 08:17 skrev Ilya Korol <llivezking at gmail.com>:

> Hi. I implemented custom REST endpoint for Keycloak Admin REST API,
> where link will be constructed.
>
> For example if you go to keycloak account client you will see in browser
> address bar something like:
>
>
> http://localhost:8081/auth/realms/test-modules/protocol/openid-connect/auth?client_id=account&redirect_uri=%2Fauth%2Frealms%2Ftest-modules%2Faccount&state=41dacfb3-fa49-499e-9797-2137c618a8a8&response_type=code&scope=openid
>
> so authenticator will play his game if you will follow similar link with
> format:
>
> ${default_authentication_link}&userId=bla&marker=blabla
>
>
> So construction of this link is pretty simple:
>
>      private String generateActivationLink(UserModel user, String
> targetClientId) {
>          ClientModel client = realm.getClientByClientId(targetClientId);
>
>          user.setSingleAttribute(ATTR_EXPIRATION,
> String.valueOf(computeExpirationTime(realm)));
>          user.setSingleAttribute(ATTR_MARKER,
> UUID.randomUUID().toString());
>
>          try {
>              URIBuilder linkUri = new URIBuilder(String.format(
>                      "%srealms/%s/protocol/openid-connect/auth",
> uriInfo.getBaseUri().toString(), realm.getName()
>              ))
>                      .addParameter("client_id", client.getClientId())
>                      .addParameter("redirect_uri", client.getBaseUrl())
>                      .addParameter("state", UUID.randomUUID().toString())
>                      .addParameter("response_type", "code")
>                      .addParameter("scope", "openid")
>                      // Add additional params
>                      .addParameter("user", user.getUserId())
>                      .addParameter("marker",
> user.getFirstAttribute(ATTR_MARKER));
>
>              return linkUri.build().toString();
>          } catch (URISyntaxException e) {
>              logger.error("Unable to construct activation link");
>              return null;
>          }
>      }
>
>
> Expiration of link or any other restriction could be implemented as
> adding attributes to UserModel while constructing the link and checking
> their values during authentication.
>
>
> The only thing that bother me now how secure is this approach, so it
> would be great if someone point me to any potential security drawbacks.
> As for me this is not less secure than standard reset credentials flow
>
>
> On 19.04.2017 15:59, Ulrik Lejon wrote:
> > Hi
> >
> > Sounds like a good idea!
> > Out of curiosity, how do you create the links? Also, will the links ever
> > expire?
> >
> > BR,
> > Ulrik
> >
> > On Wed, 19 Apr 2017, 04:02 Ilya Korol, <llivezking at gmail.com> wrote:
> >
> >> Hi recently i implemented almost same feature for our environment. I've
> >> done it via custom Authenticator implementation. This authenticator is
> >> injected in browser authentication flow as alternative execution just
> >> before cookie execution, and check request link whether he should
> >> authenticate user by this link. Here some snippet:
> >>
> >>
> >>       @Override
> >>       public void authenticate(AuthenticationFlowContext context) {
> >>           MultivaluedMap<String, String> queryParams =
> >> context.getHttpRequest().getUri().getQueryParameters();
> >>
> >>           // If uri doesn't contain appropriate query params this flow
> is
> >> not applicable,
> >>           // so we pass it by to other flow chain
> >>           if (!(queryParams.containsKey("marker") &&
> >> queryParams.containsKey("userId"))) {
> >>               context.attempted();
> >>               return;
> >>           }
> >>
> >>           // Extract params from request
> >>           String userId = queryParams.getFirst("userId");
> >>           String marker = queryParams.getFirst("marker");
> >>
> >>           RealmModel realm =
> context.getSession().getContext().getRealm();
> >>           UserModel user =
> >> context.getSession().users().getUserById(userId, realm);
> >>
> >>           // If user state doesn't match requirements this flow is not
> >> applicable,
> >>           // so we pass it by to other flow chain
> >>           if (checkConditions(user, marker, otherStruff)) {
> >>
> >>               // User could be authenticated
> >>
> >>               context.setUser(user);
> >>               context.success();
> >>           } else {
> >>               context.attempted();
> >>           }
> >>       }
> >>
> >>
> >>
> >> On 18.04.2017 19:09, Martin Johansson wrote:
> >>> Hi!
> >>>
> >>> We want to achieve the following:
> >>>
> >>> Expose a REST endpoint where an authenticated client can retrieve a
> magic
> >>> login link for a specific user. We have an ID in the attributes for the
> >>> user which enables us to get the correct user.
> >>>
> >>> The reason for this is that we need to expose the possibility to send
> >>> e-mails from other systems than Keycloak. We have other ways of
> composing
> >>> the e-mails.
> >>>
> >>> So wanted final state is that a user can click a link in his e-mail
> >> client
> >>> and be redirected to our app and be logged in.
> >>>
> >>> BR,
> >>> Martin
> >>>
> >>> ---------- Forwarded message ----------
> >>>> From: Ilya Korol <llivezking at gmail.com>
> >>>> To: keycloak-user at lists.jboss.org
> >>>> Cc:
> >>>> Bcc:
> >>>> Date: Fri, 14 Apr 2017 15:59:10 +1000
> >>>> Subject: Re: [keycloak-user] Get magic link for users to login
> >>>> Hi, could you explain more detailed what you want to achieve? As for
> my
> >>>> team we also implemented custom rest endpoint, which send customized
> >> emails
> >>>> to users. Check out
> org.keycloak.services.resources.admin.UsersResource
> >>>> for details of default link constructing. (methods:
> >> resetPasswordEmail(),
> >>>> executeActionsEmail(), sendVerifyEmail())
> >>>>
> >>>>
> >>>> On 13.04.2017 17:54, Martin Johansson wrote:
> >>>>
> >>>>> Is it possible to retrieve the magic link that are sent by e-mail via
> >> the
> >>>>> Java
> >>>>> API? We have implemented an SPI with a REST interface and would like
> to
> >>>>> get
> >>>>> the link for usage in custom e-mails.
> >>>>> Any hints which provider to be used is much appreciated.
> >>>>>
> >>>>> Regards,
> >>>>> Martin
> >>>>> _______________________________________________
> >>>>> keycloak-user mailing list
> >>>>> keycloak-user at lists.jboss.org
> >>>>> https://lists.jboss.org/mailman/listinfo/keycloak-user
> >>>>>
> >>>> _______________________________________________
> >>>> keycloak-user mailing list
> >>>> keycloak-user at lists.jboss.org
> >>>> https://lists.jboss.org/mailman/listinfo/keycloak-user
> >>>>
> >>> _______________________________________________
> >>> keycloak-user mailing list
> >>> keycloak-user at lists.jboss.org
> >>> https://lists.jboss.org/mailman/listinfo/keycloak-user
> >> _______________________________________________
> >> keycloak-user mailing list
> >> keycloak-user at lists.jboss.org
> >> https://lists.jboss.org/mailman/listinfo/keycloak-user
> >>
>
> _______________________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user
>


More information about the keycloak-user mailing list