Package ratpack.pac4j

Class RatpackPac4j


  • @Deprecated
    public class RatpackPac4j
    extends java.lang.Object
    Deprecated.
    since 1.7.0. Use Ratpack Pac4j upstream instead.
    Provides integration with the Pac4j library for authentication and authorization.

    Pac4j support many different authentication providers, such as external sources like GitHub, Twitter, Facebook etc., as well as proprietary local authentication sources.

    The authenticator(Client[]) method provides a handler that implements the authentication process, and is required in all apps wanting to use authentication.

    The requireAuth(Class, Authorizer...) method provides a handler that acts like a filter, ensuring that the user is authenticated for all requests. This can be used for requiring authentication for all requests starting with a particular request path for example.

    The userProfile(Context), login(Context, Class) and logout(Context) methods provide programmatic authentication mechanisms.

    • Field Detail

      • DEFAULT_AUTHENTICATOR_PATH

        public static final java.lang.String DEFAULT_AUTHENTICATOR_PATH
        Deprecated.
        The default path to the authenticator, "authenticator", used by authenticator(Client[]).
        See Also:
        Constant Field Values
    • Method Detail

      • authenticator

        public static Handler authenticator​(java.lang.String path,
                                            Client<?,​?>... clients)
        Deprecated.
        Creates a handler that implements authentication when the request path matches, and makes a Pac4j Clients available to downstream handlers otherwise.

        This methods performs the same function as authenticator(String, ClientsProvider), but is more convenient to use when the Client instances do not depend on the request environment.

        Parameters:
        path - the path to bind the authenticator to (relative to the current request path binding)
        clients - the supported authentication clients
        Returns:
        a handler
      • authenticator

        public static Handler authenticator​(java.lang.String path,
                                            RatpackPac4j.ClientsProvider clientsProvider)
        Deprecated.
        Creates a handler that implements authentication when the request path matches, and makes a Pac4j Clients available to downstream handlers otherwise.

        This handler MUST be BEFORE any code in the handler pipeline that tries to identify the user, such as a requireAuth(java.lang.Class<? extends org.pac4j.core.client.Client<C, U>>, org.pac4j.core.authorization.Authorizer<? super U>...) handler in the pipeline. It should be added to the handler chain via the Chain.all(Handler). That is, it should not be added with Chain.get(Handler) or any method that filters based on request method. It is common for this handler to be one of the first handlers in the pipeline.

        This handler performs two different functions, based on whether the given path matches the PathBinding.getPastBinding() component of the current path binding. If the path matches, the handler will attempt authentication, which may involve redirecting to an external auth provider, which may then redirect back to this handler. If authentication is successful, the UserProfile of the authenticated user will be placed into the session. The user will then be redirected back to the URL that initiated the authentication.

        If the path does not match, the handler will push an instance of Clients into the context registry and pass control downstream. The Clients instance will be retrieved downstream by any requireAuth(Class, Authorizer...) handler (or use of login(Context, Class).

        Parameters:
        path - the path to bind the authenticator to (relative to the current request path binding)
        clientsProvider - the provider of authentication clients
        Returns:
        a handler
      • requireAuth

        @SafeVarargs
        public static <C extends Credentials,​U extends UserProfileHandler requireAuth​(java.lang.Class<? extends Client<C,​U>> clientType,
                                                                                              Authorizer<? super U>... authorizers)
        Deprecated.
        An authentication and authorization “filter”.

        This handler can be used to ensure that a user profile is available for all downstream handlers. If there is no user profile present in the session (i.e. user not logged in), authentication will be initiated based on the given client type (i.e. redirect to the authenticator(Client[]) handler). If there is a UserProfile present in the session, this handler will push the user profile into the context registry before delegating downstream. If there is a UserProfile present in the context registry, this handler will simply delegate downstream.

        If there is a UserProfile, each of the given authorizers will be tested in turn and all must return true. If so, control will flow to the next handler. Otherwise, a 403 client error will be issued.

        This handler requires a Clients instance available in the context registry. As such, this handler should be downstream of the authenticator(Client[]) handler.

        
         import org.pac4j.core.profile.UserProfile;
         import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
         import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
         import ratpack.guice.Guice;
         import ratpack.session.SessionModule;
         import ratpack.pac4j.Pac4jSessionModule;
         import ratpack.test.embed.EmbeddedApp;
        
         import static org.junit.Assert.assertEquals;
        
         @SuppressWarnings("deprecation")
         public class Example {
           public static void main(String... args) throws Exception {
             EmbeddedApp.of(s -> s
                 .registry(Guice.registry(b -> b.module(SessionModule.class).module(Pac4jSessionModule.class)))
                 .handlers(c -> c
                     .all(ratpack.pac4j.RatpackPac4j.authenticator(new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator())))
                     .get("logout", ctx -> ratpack.pac4j.RatpackPac4j.logout(ctx).then(() -> ctx.render("logged out")))
                     .prefix("require-authn", a -> a
                         .all(ratpack.pac4j.RatpackPac4j.requireAuth(IndirectBasicAuthClient.class))
                         .get(ctx -> ctx.render("Hello " + ctx.get(UserProfile.class).getId()))
                     )
                    .prefix("require-authz", a -> a
                      .all(ratpack.pac4j.RatpackPac4j.requireAuth(IndirectBasicAuthClient.class, (ctx, profile) -> { return "special-user".equals(profile.getId()); }))
                      .get(ctx -> ctx.render("Hello " + ctx.get(UserProfile.class).getId()))
                    )
                    .get(ctx -> ctx.render("no auth required"))
                 )
             ).test(httpClient -> {
               httpClient.requestSpec(r -> r.redirects(1));
               assertEquals("no auth required", httpClient.getText());
        
               assertEquals(401, httpClient.get("require-authn").getStatusCode());
               assertEquals("Hello user", httpClient.requestSpec(r -> r.basicAuth("user", "user")).getText("require-authn"));
        
               assertEquals(403, httpClient.get("require-authz").getStatusCode());
        
               assertEquals("logged out", httpClient.getText("logout"));
               httpClient.resetRequest();
        
               assertEquals(401, httpClient.get("require-authz").getStatusCode());
               assertEquals("Hello special-user", httpClient.requestSpec(r -> r.basicAuth("special-user", "special-user")).getText("require-authz"));
             });
           }
         }
         
        Parameters:
        clientType - the client type to use to authenticate with if required
        authorizers - the authorizers to check authorizations
        Returns:
        a handler
      • login

        public static <C extends Credentials,​U extends UserProfilePromise<U> login​(Context ctx,
                                                                                           java.lang.Class<? extends Client<C,​U>> clientType)
        Deprecated.
        Logs the user in by redirecting to the authenticator, or provides the user profile if already logged in.

        This method can be used to programmatically initiate a log in, if required. If the user is already logged in, the user profile will be provided via the returned promise. If the user is not already logged in, the promise will not be fulfilled and the user will be redirected to the authenticator. As such, like requireAuth(Class, Authorizer...), this can only be used downstream of the authenticator(Client[]) handler.

        
         import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
         import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
         import ratpack.guice.Guice;
         import ratpack.http.client.ReceivedResponse;
         import ratpack.session.SessionModule;
         import ratpack.pac4j.Pac4jSessionModule;
         import ratpack.test.embed.EmbeddedApp;
        
         import java.util.Optional;
        
         import static org.junit.Assert.assertEquals;
        
         @SuppressWarnings("deprecation")
         public class Example {
           public static void main(String... args) throws Exception {
             EmbeddedApp.of(s -> s
                 .registry(Guice.registry(b -> b.module(SessionModule.class).module(Pac4jSessionModule.class)))
                 .handlers(c -> c
                     .all(ratpack.pac4j.RatpackPac4j.authenticator(new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator())))
                     .get("auth", ctx -> ratpack.pac4j.RatpackPac4j.login(ctx, IndirectBasicAuthClient.class).then(p -> ctx.redirect("/")))
                     .get(ctx ->
                         ratpack.pac4j.RatpackPac4j.userProfile(ctx)
                           .route(Optional::isPresent, p -> ctx.render("Hello " + p.get().getId()))
                           .then(p -> ctx.render("not authenticated"))
                     )
                 )
             ).test(httpClient -> {
               // user is not authenticated
               assertEquals("not authenticated", httpClient.getText());
        
               // authenticate…
               ReceivedResponse response = httpClient.requestSpec(r -> r.basicAuth("user", "user")).get("auth");
        
               // authenticated (redirected to /)
               assertEquals("Hello user", response.getBody().getText());
             });
           }
         }
         
        Parameters:
        ctx - the handling context
        clientType - the client type to authenticate with
        Returns:
        a promise for the user profile, fulfilled if logged in
      • userProfile

        public static Promise<java.util.Optional<UserProfile>> userProfile​(Context ctx)
        Deprecated.
        Obtains the logged in user's profile, if the user is logged in.

        The promised optional will be empty if the user is not authenticated.

        This method should be used if the user may have been authenticated. That is, when the the need for the profile is not downstream of an requireAuth(Class, Authorizer...) handler, as the auth handler puts the profile into the context registry for easy retrieval.

        This method returns a promise as it will attempt to load the profile from the session if it isn't already in the context registry.

        
         import io.netty.handler.codec.http.HttpHeaderNames;
         import org.pac4j.core.profile.UserProfile;
         import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
         import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
         import ratpack.guice.Guice;
         import ratpack.http.client.ReceivedResponse;
         import ratpack.session.SessionModule;
         import ratpack.pac4j.Pac4jSessionModule;
         import ratpack.test.embed.EmbeddedApp;
        
         import java.util.Optional;
        
         import static org.junit.Assert.assertEquals;
         import static org.junit.Assert.assertTrue;
        
         @SuppressWarnings("deprecation")
         public class Example {
           public static void main(String... args) throws Exception {
             EmbeddedApp.of(s -> s
                 .registry(Guice.registry(b -> b.module(SessionModule.class).module(Pac4jSessionModule.class)))
                 .handlers(c -> c
                     .all(ratpack.pac4j.RatpackPac4j.authenticator(new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator())))
                     .prefix("auth", a -> a
                         .all(ratpack.pac4j.RatpackPac4j.requireAuth(IndirectBasicAuthClient.class))
                         .get(ctx -> {
                           ctx.render("Hello " + ctx.get(UserProfile.class).getId());
                         })
                     )
                     .get("no-auth", ctx -> {
                       ratpack.pac4j.RatpackPac4j.userProfile(ctx)
                         .route(Optional::isPresent, p -> ctx.render("Hello " + p.get().getId()))
                         .then(p -> ctx.render("not authenticated"));
                     })
                 )
             ).test(httpClient -> {
               // User is not authenticated
               assertEquals("not authenticated", httpClient.getText("no-auth"));
        
               // Authenticate…
               ReceivedResponse response = httpClient.requestSpec(r -> r.redirects(0)).get("auth");
               assertEquals(302, response.getStatusCode());
               String redirectTo = response.getHeaders().get(HttpHeaderNames.LOCATION);
               assertEquals(401, httpClient.get(redirectTo).getStatusCode());
               response = httpClient.requestSpec(r -> r
                   .basicAuth("user", "user")
                   .redirects(0)
               ).post(redirectTo);
               assertEquals(302, response.getStatusCode());
               redirectTo = response.getHeaders().get(HttpHeaderNames.LOCATION);
               assertTrue(redirectTo.endsWith("/auth"));
               assertEquals("Hello user", httpClient.getText(redirectTo));
        
               // User is now authenticated
               assertEquals("Hello user", httpClient.getText("no-auth"));
             });
           }
         }
         
        Parameters:
        ctx - the handling context
        Returns:
        a promise for the user profile
        See Also:
        userProfile(Context, Class)
      • userProfile

        public static <T extends UserProfilePromise<java.util.Optional<T>> userProfile​(Context ctx,
                                                                                         java.lang.Class<T> type)
        Deprecated.
        Obtains the logged in user's profile, of the given type, if the user is logged in.

        The promised optional will be empty if the user is not authenticated. If there exists a UserProfile for the current user but it is not compatible with the requested type, the returned promise will be a failure with a ClassCastException.

        This method should be used if the user may have been authenticated. That is, when the the need for the profile is not downstream of an requireAuth(Class, Authorizer...) handler, as the auth handler puts the profile into the context registry for easy retrieval.

        This method returns a promise as it will attempt to load the profile from the session if it isn't already in the context registry.

        Type Parameters:
        T - the type of the user profile
        Parameters:
        ctx - the handling context
        type - the type of the user profile
        Returns:
        a promise for the user profile
        See Also:
        userProfile(Context)
      • logout

        public static Operation logout​(Context ctx)
        Deprecated.
        Logs out the current user, removing their profile from the session.

        The returned operation simply removes the profile from the session, regardless of whether it's actually there or not.

        
         import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
         import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
         import ratpack.guice.Guice;
         import ratpack.http.client.ReceivedResponse;
         import ratpack.session.SessionModule;
         import ratpack.pac4j.Pac4jSessionModule;
         import ratpack.test.embed.EmbeddedApp;
        
         import java.util.Optional;
        
         import static org.junit.Assert.assertEquals;
         @SuppressWarnings("deprecation")
         public class Example {
           public static void main(String... args) throws Exception {
             EmbeddedApp.of(s -> s
                 .registry(Guice.registry(b -> b.module(SessionModule.class).module(Pac4jSessionModule.class)))
                 .handlers(c -> c
                     .all(ratpack.pac4j.RatpackPac4j.authenticator(new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator())))
                     .get("auth", ctx -> ratpack.pac4j.RatpackPac4j.login(ctx, IndirectBasicAuthClient.class).then(p -> ctx.redirect("/")))
                     .get(ctx ->
                         ratpack.pac4j.RatpackPac4j.userProfile(ctx)
                           .route(Optional::isPresent, p -> ctx.render("Hello " + p.get().getId()))
                           .then(p -> ctx.render("not authenticated"))
                     )
                     .get("logout", ctx ->
                         ratpack.pac4j.RatpackPac4j.logout(ctx).then(() -> ctx.redirect("/"))
                     )
                 )
             ).test(httpClient -> {
               // user is not authenticated
               assertEquals("not authenticated", httpClient.getText());
        
               // authenticate…
               ReceivedResponse response = httpClient.requestSpec(r -> r.basicAuth("user", "user")).get("auth");
        
               // authenticated (redirected to /)
               assertEquals("Hello user", response.getBody().getText());
        
               // logout (redirected to /)
               assertEquals("not authenticated", httpClient.getText("logout"));
             });
           }
         }
         
        Parameters:
        ctx - the handling context
        Returns:
        the logout operation
      • webContext

        public static Promise<WebContext> webContext​(Context ctx)
        Deprecated.
        Adapts a Ratpack Context to a Pac4j WebContext.

        The returned WebContext does not have access to the request body. WebContext.getRequestParameters() and associated methods will not include any form parameters if the request was a form.

        Parameters:
        ctx - a Ratpack context
        Returns:
        a Pac4j web context
        Since:
        1.4