summaryrefslogtreecommitdiffstats
path: root/gerrit-server/src/main/java/com/google/gerrit/server/auth/oauth/OAuthRealm.java
blob: 0297dd4a663e1350ec9774c5553c1f08d9262f54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.auth.oauth;

import com.google.common.base.Strings;
import com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider;
import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Account.FieldName;
import com.google.gerrit.server.account.AbstractRealm;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

@Singleton
public class OAuthRealm extends AbstractRealm {
  private final DynamicMap<OAuthLoginProvider> loginProviders;
  private final Set<FieldName> editableAccountFields;

  @Inject
  OAuthRealm(DynamicMap<OAuthLoginProvider> loginProviders,
      @GerritServerConfig Config config) {
    this.loginProviders = loginProviders;
    this.editableAccountFields = new HashSet<>();
    // User name should be always editable, because not all OAuth providers
    // expose them
    editableAccountFields.add(FieldName.USER_NAME);
    if (config.getBoolean("oauth", null, "allowEditFullName", false)) {
      editableAccountFields.add(FieldName.FULL_NAME);
    }
    if (config.getBoolean("oauth", null, "allowRegisterNewEmail", false)) {
      editableAccountFields.add(FieldName.REGISTER_NEW_EMAIL);
    }
  }

  @Override
  public boolean allowsEdit(FieldName field) {
    return editableAccountFields.contains(field);
  }

  /**
   * Authenticates with the {@link OAuthLoginProvider} specified
   * in the authentication request.
   *
   * {@link AccountManager} calls this method without password
   * if authenticity of the user has already been established.
   * In that case the {@link AuthRequest} is supposed to contain
   * a resolved email address and we can skip the authentication
   * request to the {@code OAuthLoginService}.
   *
   * @param who the authentication request.
   *
   * @return the authentication request with resolved email address
   * and display name in case the authenticity of the user could
   * be established; otherwise {@code who} is returned unchanged.
   *
   * @throws AccountException if the authentication request with
   * the OAuth2 server failed or no {@code OAuthLoginProvider} was
   * available to handle the request.
   */
  @Override
  public AuthRequest authenticate(AuthRequest who) throws AccountException {
    if (Strings.isNullOrEmpty(who.getPassword()) &&
        !Strings.isNullOrEmpty(who.getEmailAddress())) {
      return who;
    }

    if (Strings.isNullOrEmpty(who.getAuthPlugin())
        || Strings.isNullOrEmpty(who.getAuthProvider())) {
      throw new AccountException("Cannot authenticate");
    }
    OAuthLoginProvider loginProvider =
        loginProviders.get(who.getAuthPlugin(), who.getAuthProvider());
    if (loginProvider == null) {
      throw new AccountException("Cannot authenticate");
    }

    OAuthUserInfo userInfo;
    try {
      userInfo = loginProvider.login(who.getUserName(), who.getPassword());
    } catch (IOException e) {
      throw new AccountException("Cannot authenticate", e);
    }
    if (userInfo == null) {
      throw new AccountException("Cannot authenticate");
    }
    if (!Strings.isNullOrEmpty(userInfo.getEmailAddress())
        && (Strings.isNullOrEmpty(who.getUserName())
            || !allowsEdit(FieldName.REGISTER_NEW_EMAIL))) {
      who.setEmailAddress(userInfo.getEmailAddress());
    }
    if (!Strings.isNullOrEmpty(userInfo.getDisplayName())
        && (Strings.isNullOrEmpty(who.getDisplayName())
            || !allowsEdit(FieldName.FULL_NAME))) {
      who.setDisplayName(userInfo.getDisplayName());
    }
    return who;
  }

  @Override
  public void onCreateAccount(AuthRequest who, Account account) {
  }

  @Override
  public Account.Id lookup(String accountName) {
    return null;
  }
}