source: ComponentRegistry/branches/ComponentRegistry-2.0/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/rest/AuthenticationRestService.java @ 5975

Last change on this file since 5975 was 5975, checked in by Twan Goosen, 9 years ago

Authentication resource: 'redirect' param
Created two test forms in index.jsp

File size: 5.0 KB
Line 
1package clarin.cmdi.componentregistry.rest;
2
3import clarin.cmdi.componentregistry.AuthenticationRequiredException;
4import clarin.cmdi.componentregistry.ComponentRegistryFactory;
5import clarin.cmdi.componentregistry.UserCredentials;
6import clarin.cmdi.componentregistry.impl.database.ValidationException;
7import clarin.cmdi.componentregistry.model.AuthenticationInfo;
8import com.google.common.base.Strings;
9import com.wordnik.swagger.annotations.Api;
10import com.wordnik.swagger.annotations.ApiOperation;
11import com.wordnik.swagger.annotations.ApiResponse;
12import com.wordnik.swagger.annotations.ApiResponses;
13import java.net.URI;
14import java.security.Principal;
15import javax.ws.rs.DefaultValue;
16import javax.ws.rs.GET;
17import javax.ws.rs.POST;
18import javax.ws.rs.Path;
19import javax.ws.rs.Produces;
20import javax.ws.rs.QueryParam;
21import javax.ws.rs.core.Context;
22import javax.ws.rs.core.MediaType;
23import javax.ws.rs.core.Response;
24import javax.ws.rs.core.SecurityContext;
25import javax.ws.rs.core.UriInfo;
26import org.json.JSONException;
27import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29import org.springframework.stereotype.Service;
30import org.springframework.transaction.annotation.Transactional;
31
32/**
33 * Authentication resource to be used by the client to retrieve the current
34 * authentication status and/or to force an authentication request if the user
35 * is not authenticated.
36 *
37 * <p>
38 * A 'GET' on this resource will return a JSON or XML structure with the
39 * following information:</p>
40 * <ul>
41 * <li>authentication (true/false)</li>
42 * <li>username (string)</li>
43 * <li>displayName</li>
44 * (string)
45 * </ul>
46 *
47 * <p>
48 * A 'POST' to this resource will trigger an authentication request (by means of
49 * a 401) response code if the user is not yet authenticated. In case of a
50 * successful authentication, it will respond with a redirect (303) to this same
51 * resource.</p>
52 *
53 * <p>
54 * A query parameter 'redirect' is accepted on the GET. If it is present, the
55 * service will respond with a redirect to the provided URI. This way, the
56 * client can make sure that the user is lead back to the front end in the
57 * desired state. Passing the 'redirect' query parameter in the POST response
58 * will cause it to be preserved in the redirect to the GET. To execute a
59 * 'login' action, a front end application will therefore typically send a POST
60 * to {@code <SERVICE_BASE_URI>/authentication?redirect=<FRONT_END_URI>}.</p>
61 *
62 * @author Twan Goosen <twan.goosen@mpi.nl>
63 */
64@Path("/authentication")
65@Service
66@Transactional(rollbackFor = {Exception.class, ValidationException.class})
67@Api(value = "/authentication", description = "REST resource for handling the authentication status", produces = MediaType.APPLICATION_XML)
68public class AuthenticationRestService {
69
70    private final Logger logger = LoggerFactory.getLogger(AuthenticationRestService.class);
71
72    @Context
73    private SecurityContext security;
74    @Context
75    private UriInfo uriInfo;
76
77    @GET
78    @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
79    @ApiOperation(value = "Information on the current authentication state. Pass 'redirect' query parameter to make this method redirect to the URI specified as its value.")
80    @ApiResponses(value = {
81        @ApiResponse(code = 200, message = "If no query parameters are passed, with the authentications status in its body"),
82        @ApiResponse(code = 303, message = "A redirect to the URI provided as the value of the 'redirect' parameter")
83    })
84    public Response getAuthenticationInformation(@QueryParam("redirect") @DefaultValue("") String redirectUri) throws JSONException, AuthenticationRequiredException {
85        final Principal userPrincipal = security.getUserPrincipal();
86
87        final AuthenticationInfo authInfo;
88        if (userPrincipal == null || ComponentRegistryFactory.ANONYMOUS_USER.equals(userPrincipal.getName())) {
89            authInfo = new AuthenticationInfo(false);
90        } else {
91            authInfo = new AuthenticationInfo(new UserCredentials(userPrincipal));
92        }
93
94        if (Strings.isNullOrEmpty(redirectUri)) {
95            return Response.ok(authInfo).build();
96        } else {
97            return Response.seeOther(URI.create(redirectUri)).entity(authInfo).build();
98        }
99    }
100
101    @POST
102    @ApiOperation(value = "Triggers the service to require the client to authenticate by means of the configured authentication mechanism. Notice that this might require user interaction!")
103    @ApiResponses(value = {
104        @ApiResponse(code = 303, message = "A redirect, either to a Shibboleth authentication page/discovery service or other identification mechanism, and ultimately to the same URI as requested (which should be picked up as a GET)"),
105        @ApiResponse(code = 401, message = "If unauthenticated, a request to authenticate may be returned (not in case of Shibboleth authentication)")
106    })
107    public Response triggerAuthenticationRequest() {
108        logger.debug("Client has triggered authentication request");
109
110        //done - redirect to GET
111        return Response.seeOther(uriInfo.getRequestUri()).build();
112    }
113}
Note: See TracBrowser for help on using the repository browser.