1   /*
2    * Copyright 2018 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package com.linecorp.centraldogma.server.auth;
17  
18  import static com.linecorp.centraldogma.internal.api.v1.HttpApiV1Constants.API_V0_PATH_PREFIX;
19  import static com.linecorp.centraldogma.internal.api.v1.HttpApiV1Constants.API_V1_PATH_PREFIX;
20  
21  import java.util.Set;
22  
23  import javax.annotation.Nullable;
24  
25  import com.google.common.collect.ImmutableList;
26  import com.google.common.collect.ImmutableSet;
27  
28  import com.linecorp.armeria.common.HttpResponse;
29  import com.linecorp.armeria.common.HttpStatus;
30  import com.linecorp.armeria.server.HttpService;
31  import com.linecorp.armeria.server.HttpServiceWithRoutes;
32  import com.linecorp.armeria.server.Route;
33  import com.linecorp.armeria.server.Service;
34  
35  /**
36   * An interface which configures the authentication layer for the Central Dogma server.
37   */
38  public interface AuthProvider {
39      /**
40       * A login page path for the web console. If a user, who has not logged into the web console yet,
41       * opens the web console, the web browser would bring the user to the login page.
42       */
43      String LOGIN_PATH = "/link/auth/login";
44  
45      /**
46       * A logout page path for the web console. If a user clicks the logout button on the navigation bar,
47       * the web browser would bring the user to the logout page.
48       */
49      String LOGOUT_PATH = "/link/auth/logout";
50  
51      /**
52       * A base path of the built-in web app.
53       */
54      String BUILTIN_WEB_BASE_PATH = "/web/auth";
55  
56      /**
57       * A path which provides a built-in HTML login form to a user.
58       */
59      String BUILTIN_WEB_LOGIN_PATH = BUILTIN_WEB_BASE_PATH + "/login";
60  
61      /**
62       * A path which provides a built-in HTML logout page to a user.
63       */
64      String BUILTIN_WEB_LOGOUT_PATH = BUILTIN_WEB_BASE_PATH + "/logout";
65  
66      /**
67       * A set of {@link Route}s which handles a login request. It is necessary only if
68       * an authentication protocol requires a login feature provided by the server.
69       */
70      Set<Route> LOGIN_API_ROUTES =
71              ImmutableSet.of(Route.builder().exact(API_V0_PATH_PREFIX + "authenticate").build(),
72                              Route.builder().exact(API_V1_PATH_PREFIX + "login").build());
73  
74      /**
75       * A set of {@link Route}s which handles a logout request. It is necessary only if
76       * an authentication protocol requires a logout feature provided by the server.
77       */
78      Set<Route> LOGOUT_API_ROUTES =
79              ImmutableSet.of(Route.builder().exact(API_V0_PATH_PREFIX + "logout").build(),
80                              Route.builder().exact(API_V1_PATH_PREFIX + "logout").build());
81  
82      /**
83       * Returns a {@link Service} which handles a login request from a web browser. By default,
84       * the browser would bring a user to the built-in web login page served on {@value BUILTIN_WEB_LOGIN_PATH}.
85       */
86      default HttpService webLoginService() {
87          // Redirect to the default page: /link/auth/login -> /web/auth/login
88          return (ctx, req) -> {
89              String returnTo = ctx.queryParam("return_to");
90              if (returnTo != null) {
91                  returnTo += BUILTIN_WEB_LOGIN_PATH;
92              } else {
93                  returnTo = BUILTIN_WEB_LOGIN_PATH;
94              }
95              return HttpResponse.ofRedirect(HttpStatus.MOVED_PERMANENTLY, returnTo);
96          };
97      }
98  
99      /**
100      * Returns a {@link Service} which handles a logout request from a web browser. By default,
101      * the browser would bring a user to the built-in web logout page served on
102      * {@value BUILTIN_WEB_LOGOUT_PATH}.
103      */
104     default HttpService webLogoutService() {
105         // Redirect to the default page: /link/auth/logout -> /web/auth/logout
106         return (ctx, req) -> {
107             String returnTo = ctx.queryParam("return_to");
108             if (returnTo != null) {
109                 returnTo += BUILTIN_WEB_LOGOUT_PATH;
110             } else {
111                 returnTo = BUILTIN_WEB_LOGOUT_PATH;
112             }
113             return HttpResponse.ofRedirect(HttpStatus.MOVED_PERMANENTLY, returnTo);
114         };
115     }
116 
117     /**
118      * Returns a {@link Service} which handles a login request sent from the built-in web login page or
119      * somewhere implemented by an {@link AuthProvider}. This service would be added to the server
120      * with {@link #LOGIN_API_ROUTES} only if it is provided.
121      */
122     @Nullable
123     default HttpService loginApiService() {
124         return null;
125     }
126 
127     /**
128      * Returns a {@link Service} which handles a logout request sent from the built-in web logout page or
129      * somewhere implemented by an {@link AuthProvider}. This service would be added to the server
130      * with {@link #LOGOUT_API_ROUTES}. If it is not provided, a default service would be added
131      * because the web console provides a logout button on the navigation bar by default.
132      */
133     @Nullable
134     default HttpService logoutApiService() {
135         return null;
136     }
137 
138     /**
139      * Returns additional {@link Service}s which are required for working this {@link AuthProvider}
140      * well.
141      */
142     default Iterable<HttpServiceWithRoutes> moreServices() {
143         return ImmutableList.of();
144     }
145 }