blob: a357c675cb358995fba5457515ad088d1948569d [file] [log] [blame]
Michael Hanl19390652016-01-16 11:01:24 +01001package de.ids_mannheim.korap.web.service.full;
Michael Hanlfb839b92015-09-19 21:32:34 +02002
3import com.sun.jersey.spi.container.ContainerRequest;
4import com.sun.jersey.spi.container.ResourceFilters;
5import de.ids_mannheim.korap.config.BeanConfiguration;
6import de.ids_mannheim.korap.exceptions.KustvaktException;
7import de.ids_mannheim.korap.exceptions.StatusCodes;
8import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
9import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
10import de.ids_mannheim.korap.user.Attributes;
11import de.ids_mannheim.korap.user.TokenContext;
12import de.ids_mannheim.korap.user.User;
13import de.ids_mannheim.korap.user.UserSettings;
14import de.ids_mannheim.korap.utils.JsonUtils;
15import de.ids_mannheim.korap.utils.KustvaktLogger;
16import de.ids_mannheim.korap.utils.ServiceVersion;
17import de.ids_mannheim.korap.web.KustvaktServer;
18import de.ids_mannheim.korap.web.filter.AuthFilter;
19import de.ids_mannheim.korap.web.filter.DefaultFilter;
20import de.ids_mannheim.korap.web.filter.PiwikFilter;
Michael Hanl482f30d2015-09-25 12:39:46 +020021import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
Michael Hanlfb839b92015-09-19 21:32:34 +020022import org.slf4j.Logger;
23
24import javax.ws.rs.*;
25import javax.ws.rs.core.*;
26import java.util.HashMap;
27import java.util.List;
28import java.util.Locale;
29import java.util.Map;
30
31//import com.sun.xml.internal.messaging.saaj.util.Base64;
32
33/**
34 * @author hanl
35 * @date 24/01/2014
36 */
37@Path(KustvaktServer.API_VERSION + "/auth")
38@ResourceFilters({ PiwikFilter.class })
39@Produces(MediaType.TEXT_HTML + ";charset=utf-8")
40public class AuthService {
41
42 //todo: bootstrap function to transmit certain default configuration settings and examples (example user queries,
43 // default usersettings, etc.)
Michael Hanlfdd9a012015-11-13 15:56:38 +010044 private static Logger jlog = KustvaktLogger.getLogger(AuthService.class);
Michael Hanlfb839b92015-09-19 21:32:34 +020045
46 private AuthenticationManagerIface controller;
47 // private SendMail mail;
48
49 public AuthService() {
50 this.controller = BeanConfiguration.getBeans()
51 .getAuthenticationManager();
52 //todo: replace with real property values
53 // this.mail = new SendMail(ExtConfiguration.getMailProperties());
54 }
55
56 /**
57 * represents json string with data. All GUI clients can access this method to get certain default values
58 * --> security checks?
59 *
60 * @return String
61 */
62 @GET
63 @Path("bootstrap")
64 @Produces(MediaType.APPLICATION_JSON)
65 public Response bootstrap() {
66 Map m = new HashMap();
67 m.put("settings", new UserSettings().toObjectMap());
68 m.put("ql", BeanConfiguration.getBeans().getConfiguration()
69 .getQueryLanguages());
70 m.put("SortTypes", null); // types of sorting that are supported!
71 m.put("version", ServiceVersion.getAPIVersion());
72 return Response.ok(JsonUtils.toJSON(m)).build();
73 }
74
Michael Hanl19390652016-01-16 11:01:24 +010075
76 // fixme: moved to user
Michael Hanlfb839b92015-09-19 21:32:34 +020077 @GET
78 @Path("status")
79 @ResourceFilters({ AuthFilter.class, DefaultFilter.class })
80 public Response getStatus(@Context SecurityContext context,
81 @HeaderParam(ContainerRequest.USER_AGENT) String agent,
82 @HeaderParam(ContainerRequest.HOST) String host,
83 @Context Locale locale) {
84 TokenContext ctx = (TokenContext) context.getUserPrincipal();
85 return Response.ok(ctx.toJSON()).build();
86 }
87
88 @GET
89 @Path("apiToken")
90 public Response requestAPIToken(@Context HttpHeaders headers,
91 @Context Locale locale,
92 @HeaderParam(ContainerRequest.USER_AGENT) String agent,
93 @HeaderParam(ContainerRequest.HOST) String host,
94 @HeaderParam("referer-url") String referer,
Michael Hanl19390652016-01-16 11:01:24 +010095 @QueryParam("scope") String scopes) {
Michael Hanlfb839b92015-09-19 21:32:34 +020096 List<String> auth = headers
97 .getRequestHeader(ContainerRequest.AUTHORIZATION);
98
99 if (auth == null)
Michael Hanl482f30d2015-09-25 12:39:46 +0200100 throw KustvaktResponseHandler
Michael Hanlfb839b92015-09-19 21:32:34 +0200101 .throwit(StatusCodes.PERMISSION_DENIED);
102 String[] values = BasicHttpAuth.decode(auth.get(0));
103
104 // "Invalid syntax for username and password"
105 if (values == null)
Michael Hanl482f30d2015-09-25 12:39:46 +0200106 throw KustvaktResponseHandler
Michael Hanlfb839b92015-09-19 21:32:34 +0200107 .throwit(StatusCodes.PERMISSION_DENIED);
108
109 if (values[0].equalsIgnoreCase("null") | values[1]
110 .equalsIgnoreCase("null"))
111 // is actual an invalid request
Michael Hanl482f30d2015-09-25 12:39:46 +0200112 throw KustvaktResponseHandler
Michael Hanlfb839b92015-09-19 21:32:34 +0200113 .throwit(StatusCodes.REQUEST_INVALID);
114
115 Map<String, Object> attr = new HashMap<>();
Michael Hanl482f30d2015-09-25 12:39:46 +0200116 if (scopes != null && !scopes.isEmpty())
117 attr.put(Attributes.SCOPES, scopes);
Michael Hanlfb839b92015-09-19 21:32:34 +0200118 attr.put(Attributes.HOST, host);
119 attr.put(Attributes.USER_AGENT, agent);
120 TokenContext context;
121 try {
122 User user = controller.authenticate(0, values[0], values[1], attr);
123 this.controller.getUserDetails(user);
124 context = controller.createTokenContext(user, attr,
125 Attributes.API_AUTHENTICATION);
126 }catch (KustvaktException e) {
Michael Hanl482f30d2015-09-25 12:39:46 +0200127 throw KustvaktResponseHandler.throwit(e);
Michael Hanlfb839b92015-09-19 21:32:34 +0200128 }
129
130 return Response.ok(context.toResponse()).build();
131 }
132
133 // todo:
134 @Deprecated
135 @GET
136 @Path("refresh")
137 public Response refresh(@Context SecurityContext context,
138 @Context Locale locale) {
139 TokenContext ctx = (TokenContext) context.getUserPrincipal();
140 TokenContext newContext;
141
142 // try {
143 // newContext = controller.refresh(ctx);
144 // }catch (KorAPException e) {
145 // KorAPLogger.ERROR_LOGGER.error("Exception encountered!", e);
Michael Hanl482f30d2015-09-25 12:39:46 +0200146 // throw KustvaktResponseHandler.throwit(e);
Michael Hanlfb839b92015-09-19 21:32:34 +0200147 // }
148 // return Response.ok().entity(newContext.getToken()).build();
149 return null;
150 }
151
152 @GET
153 @Path("sessionToken")
154 public Response requestSession(@Context HttpHeaders headers,
155 @Context Locale locale,
156 @HeaderParam(ContainerRequest.USER_AGENT) String agent,
157 @HeaderParam(ContainerRequest.HOST) String host) {
158 List<String> auth = headers
159 .getRequestHeader(ContainerRequest.AUTHORIZATION);
160
161 if (auth == null)
Michael Hanl482f30d2015-09-25 12:39:46 +0200162 throw KustvaktResponseHandler
Michael Hanlfb839b92015-09-19 21:32:34 +0200163 .throwit(StatusCodes.PERMISSION_DENIED);
164
165 String[] values = BasicHttpAuth.decode(auth.get(0));
166 // authentication = StringUtils.stripTokenType(authentication);
167 // String[] values = new String(
168 // DatatypeConverter.parseBase64Binary(authentication)).split(":");
169 // String[] values = Base64.base64Decode(authentication).split(":");
170
171 // "Invalid syntax for username and password"
172 if (values == null)
Michael Hanl482f30d2015-09-25 12:39:46 +0200173 throw KustvaktResponseHandler
Michael Hanlfb839b92015-09-19 21:32:34 +0200174 .throwit(StatusCodes.PERMISSION_DENIED);
175
176 if (values[0].equalsIgnoreCase("null") | values[1]
177 .equalsIgnoreCase("null"))
Michael Hanl482f30d2015-09-25 12:39:46 +0200178 throw KustvaktResponseHandler
Michael Hanlfb839b92015-09-19 21:32:34 +0200179 .throwit(StatusCodes.REQUEST_INVALID);
180
181 Map<String, Object> attr = new HashMap<>();
182 attr.put(Attributes.HOST, host);
183 attr.put(Attributes.USER_AGENT, agent);
184 TokenContext context;
185 try {
186 User user = controller.authenticate(0, values[0], values[1], attr);
187 context = controller.createTokenContext(user, attr,
188 Attributes.SESSION_AUTHENTICATION);
189 }catch (KustvaktException e) {
Michael Hanl482f30d2015-09-25 12:39:46 +0200190 throw KustvaktResponseHandler.throwit(e);
Michael Hanlfb839b92015-09-19 21:32:34 +0200191 }
192 return Response.ok().entity(context.toJSON()).build();
193 }
194
195 // fixme: security issues: setup shibboleth compatible authentication system
196 // todo: will be purged with token authentication --> shib is client side
197 @POST
198 @Consumes("application/x-www-form-urlencoded")
199 @Produces("application/json")
200 @Path("shibboleth")
201 public Response loginshib(@Context HttpHeaders headers,
202 @Context Locale locale,
203 @HeaderParam(ContainerRequest.USER_AGENT) String agent,
204 @HeaderParam(ContainerRequest.HOST) String host,
205 @QueryParam("client_id") String client_id) {
206
207 // the shibfilter decrypted the values
208 // define default provider for returned access token strategy?!
209
210 Map<String, Object> attr = new HashMap<>();
211 attr.put(Attributes.HOST, host);
212 attr.put(Attributes.USER_AGENT, agent);
213
214 TokenContext context;
215
216 try {
217 // todo: distinguish type KorAP/Shibusers
218 User user = controller.authenticate(1, null, null, attr);
219 context = controller.createTokenContext(user, attr, null);
220 }catch (KustvaktException e) {
Michael Hanl482f30d2015-09-25 12:39:46 +0200221 throw KustvaktResponseHandler.throwit(e);
Michael Hanlfb839b92015-09-19 21:32:34 +0200222 }
223 return Response.ok().entity(context.toJSON()).build();
224 }
Michael Hanl19390652016-01-16 11:01:24 +0100225
226 //fixme: moved from userservice
227 @GET
228 @Path("logout")
229 @ResourceFilters({ AuthFilter.class, DefaultFilter.class,
230 PiwikFilter.class })
231 public Response logout(@Context SecurityContext ctx,
232 @Context Locale locale) {
233 TokenContext context = (TokenContext) ctx.getUserPrincipal();
234 try {
235 controller.logout(context);
236 }catch (KustvaktException e) {
237 jlog.error("Logout Exception", e);
238 throw KustvaktResponseHandler.throwit(e);
239 }
240 return Response.ok().build();
241 }
242
Michael Hanlfb839b92015-09-19 21:32:34 +0200243}