1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.linecorp.centraldogma.server.internal.api.auth;
18
19 import static java.util.Objects.requireNonNull;
20 import static java.util.concurrent.CompletableFuture.completedFuture;
21
22 import java.net.InetSocketAddress;
23 import java.net.SocketAddress;
24 import java.util.concurrent.CompletionStage;
25 import java.util.function.Function;
26
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 import com.linecorp.armeria.common.HttpRequest;
31 import com.linecorp.armeria.common.auth.OAuth2Token;
32 import com.linecorp.armeria.common.logging.LogLevel;
33 import com.linecorp.armeria.common.util.Exceptions;
34 import com.linecorp.armeria.common.util.UnmodifiableFuture;
35 import com.linecorp.armeria.server.ServiceRequestContext;
36 import com.linecorp.armeria.server.auth.AuthTokenExtractors;
37 import com.linecorp.armeria.server.auth.Authorizer;
38 import com.linecorp.centraldogma.server.internal.admin.auth.AuthUtil;
39 import com.linecorp.centraldogma.server.internal.api.HttpApiUtil;
40 import com.linecorp.centraldogma.server.metadata.Token;
41 import com.linecorp.centraldogma.server.metadata.TokenNotFoundException;
42 import com.linecorp.centraldogma.server.metadata.Tokens;
43 import com.linecorp.centraldogma.server.metadata.UserWithToken;
44
45
46
47
48 public class ApplicationTokenAuthorizer implements Authorizer<HttpRequest> {
49
50 private static final Logger logger = LoggerFactory.getLogger(
51 ApplicationTokenAuthorizer.class);
52
53 private final Function<String, Token> tokenLookupFunc;
54
55 public ApplicationTokenAuthorizer(Function<String, Token> tokenLookupFunc) {
56 this.tokenLookupFunc = requireNonNull(tokenLookupFunc, "tokenLookupFunc");
57 }
58
59 @Override
60 public CompletionStage<Boolean> authorize(ServiceRequestContext ctx, HttpRequest data) {
61 final OAuth2Token token = AuthTokenExtractors.oAuth2().apply(data.headers());
62 if (token == null || !Tokens.isValidSecret(token.accessToken())) {
63 return completedFuture(false);
64 }
65
66 try {
67 final Token appToken = tokenLookupFunc.apply(token.accessToken());
68 if (appToken != null && appToken.isActive()) {
69 final String appId = appToken.appId();
70 final StringBuilder login = new StringBuilder(appId);
71 final SocketAddress ra = ctx.remoteAddress();
72 if (ra instanceof InetSocketAddress) {
73 login.append('@').append(((InetSocketAddress) ra).getHostString());
74 }
75 ctx.logBuilder().authenticatedUser("app/" + appId);
76 final UserWithToken user = new UserWithToken(login.toString(), appToken);
77 AuthUtil.setCurrentUser(ctx, user);
78 HttpApiUtil.setVerboseResponses(ctx, user);
79 return UnmodifiableFuture.completedFuture(true);
80 }
81 return UnmodifiableFuture.completedFuture(false);
82 } catch (Throwable cause) {
83 cause = Exceptions.peel(cause);
84 final LogLevel level;
85 if (cause instanceof IllegalArgumentException ||
86 cause instanceof TokenNotFoundException) {
87 level = LogLevel.DEBUG;
88 } else {
89 level = LogLevel.WARN;
90 }
91 level.log(logger, "Failed to authorize an application token: token={}, addr={}",
92 token.accessToken(), ctx.clientAddress(), cause);
93 return UnmodifiableFuture.completedFuture(false);
94 }
95 }
96 }