Skip to content

Commit

Permalink
Merge pull request #324 from karatkep/21515-email-claim-configuration
Browse files Browse the repository at this point in the history
feat(oidc): email claim configuration
  • Loading branch information
tolusha authored Jul 6, 2022
2 parents 814950c + 9ade8d4 commit 1d87137
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2012-2021 Red Hat, Inc.
# Copyright (c) 2012-2022 Red Hat, Inc.
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
Expand Down Expand Up @@ -110,6 +110,10 @@ che.oidc.allowed_clock_skew_sec=3
# `name` in Dex installations.
che.oidc.username_claim=NULL

# Email claim to be used when parsing JWT token.
# If not defined, the fallback value is 'email'.
che.oidc.email_claim=NULL

# Base URL of an alternate OIDC provider that provides
# a discovery endpoint as detailed in the following specification
# link:https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Obtaining OpenID Provider Configuration Information]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand Down Expand Up @@ -43,6 +43,7 @@ public class OIDCInfoProvider implements Provider<OIDCInfo> {
OIDC_SETTING_PREFIX + "auth_internal_server_url";
public static final String OIDC_PROVIDER_SETTING = OIDC_SETTING_PREFIX + "oidc_provider";
public static final String OIDC_USERNAME_CLAIM_SETTING = OIDC_SETTING_PREFIX + "username_claim";
public static final String OIDC_EMAIL_CLAIM_SETTING = OIDC_SETTING_PREFIX + "email_claim";
public static final String OIDC_ALLOWED_CLOCK_SKEW_SEC =
OIDC_SETTING_PREFIX + "allowed_clock_skew_sec";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand All @@ -12,6 +12,7 @@
package org.eclipse.che.multiuser.oidc.filter;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.che.multiuser.oidc.OIDCInfoProvider.OIDC_EMAIL_CLAIM_SETTING;
import static org.eclipse.che.multiuser.oidc.OIDCInfoProvider.OIDC_USERNAME_CLAIM_SETTING;

import io.jsonwebtoken.Claims;
Expand Down Expand Up @@ -40,19 +41,22 @@
*
* <p>It also makes sure that User is present in Che database. If not, it will create the User from
* JWT token claims. The username claim is configured with {@link
* org.eclipse.che.multiuser.oidc.OIDCInfoProvider#OIDC_USERNAME_CLAIM_SETTING}.
* org.eclipse.che.multiuser.oidc.OIDCInfoProvider#OIDC_USERNAME_CLAIM_SETTING}. The email claim is
* configured with {@link org.eclipse.che.multiuser.oidc.OIDCInfoProvider#OIDC_EMAIL_CLAIM_SETTING}.
*/
@Singleton
public class OidcTokenInitializationFilter
extends MultiUserEnvironmentInitializationFilter<Jws<Claims>> {
private static final String EMAIL_CLAIM = "email";
private static final String NAME_CLAIM = "name";
protected static final String DEFAULT_USERNAME_CLAIM = NAME_CLAIM;
protected static final String DEFAULT_EMAIL_CLAIM = EMAIL_CLAIM;

private final JwtParser jwtParser;
private final PermissionChecker permissionChecker;
private final UserManager userManager;
private final String usernameClaim;
private final String emailClaim;

@Inject
public OidcTokenInitializationFilter(
Expand All @@ -61,12 +65,14 @@ public OidcTokenInitializationFilter(
SessionStore sessionStore,
RequestTokenExtractor tokenExtractor,
UserManager userManager,
@Nullable @Named(OIDC_USERNAME_CLAIM_SETTING) String usernameClaim) {
@Nullable @Named(OIDC_USERNAME_CLAIM_SETTING) String usernameClaim,
@Nullable @Named(OIDC_EMAIL_CLAIM_SETTING) String emailClaim) {
super(sessionStore, tokenExtractor);
this.permissionChecker = permissionChecker;
this.jwtParser = jwtParser;
this.userManager = userManager;
this.usernameClaim = isNullOrEmpty(usernameClaim) ? DEFAULT_USERNAME_CLAIM : usernameClaim;
this.emailClaim = isNullOrEmpty(emailClaim) ? DEFAULT_EMAIL_CLAIM : emailClaim;
}

@Override
Expand All @@ -86,7 +92,7 @@ protected Subject extractSubject(String token, Jws<Claims> processedToken) {
User user =
userManager.getOrCreateUser(
claims.getSubject(),
claims.get(EMAIL_CLAIM, String.class),
claims.get(emailClaim, String.class),
claims.get(usernameClaim, String.class));
return new AuthorizedSubject(
new SubjectImpl(user.getName(), user.getId(), token, false), permissionChecker);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand All @@ -11,6 +11,7 @@
*/
package org.eclipse.che.multiuser.oidc.filter;

import static org.eclipse.che.multiuser.oidc.filter.OidcTokenInitializationFilter.DEFAULT_EMAIL_CLAIM;
import static org.eclipse.che.multiuser.oidc.filter.OidcTokenInitializationFilter.DEFAULT_USERNAME_CLAIM;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -46,6 +47,7 @@ public class OidcTokenInitializationFilterTest {
@Mock private RequestTokenExtractor tokenExtractor;
@Mock private UserManager userManager;
private final String usernameClaim = "blabolClaim";
private final String emailClaim = "pafturClaim";
private final String TEST_USERNAME = "jondoe";
private final String TEST_USER_EMAIL = "jon@doe";
private final String TEST_USERID = "jon1337";
Expand All @@ -66,11 +68,12 @@ public void setUp() {
sessionStore,
tokenExtractor,
userManager,
usernameClaim);
usernameClaim,
emailClaim);

lenient().when(jwsClaims.getBody()).thenReturn(claims);
lenient().when(claims.getSubject()).thenReturn(TEST_USERID);
lenient().when(claims.get("email", String.class)).thenReturn(TEST_USER_EMAIL);
lenient().when(claims.get(emailClaim, String.class)).thenReturn(TEST_USER_EMAIL);
lenient().when(claims.get(usernameClaim, String.class)).thenReturn(TEST_USERNAME);
}

Expand Down Expand Up @@ -124,7 +127,8 @@ public void testDefaultUsernameClaimWhenEmpty(String customUsernameClaim)
sessionStore,
tokenExtractor,
userManager,
customUsernameClaim);
customUsernameClaim,
emailClaim);
User createdUser = mock(User.class);
when(createdUser.getId()).thenReturn(TEST_USERID);
when(createdUser.getName()).thenReturn(TEST_USERNAME);
Expand All @@ -142,8 +146,42 @@ public void testDefaultUsernameClaimWhenEmpty(String customUsernameClaim)
verify(claims, never()).get(usernameClaim, String.class);
}

@Test(dataProvider = "emailClaims")
public void testDefaultEmailClaimWhenEmpty(String customEmailClaim)
throws ServerException, ConflictException {
tokenInitializationFilter =
new OidcTokenInitializationFilter(
permissionsChecker,
jwtParser,
sessionStore,
tokenExtractor,
userManager,
usernameClaim,
customEmailClaim);
User createdUser = mock(User.class);
when(createdUser.getId()).thenReturn(TEST_USERID);
when(createdUser.getName()).thenReturn(TEST_USERNAME);
when(userManager.getOrCreateUser(TEST_USERID, TEST_USER_EMAIL, TEST_USERNAME))
.thenReturn(createdUser);
when(claims.get(DEFAULT_EMAIL_CLAIM, String.class)).thenReturn(TEST_USER_EMAIL);

var subject = tokenInitializationFilter.extractSubject(TEST_TOKEN, jwsClaims);

assertEquals(subject.getUserId(), TEST_USERID);
assertEquals(subject.getUserName(), TEST_USERNAME);
assertEquals(subject.getToken(), TEST_TOKEN);
verify(userManager).getOrCreateUser(TEST_USERID, TEST_USER_EMAIL, TEST_USERNAME);
verify(claims).get(DEFAULT_EMAIL_CLAIM, String.class);
verify(claims, never()).get(emailClaim, String.class);
}

@DataProvider
public static Object[][] usernameClaims() {
return new Object[][] {{""}, {null}};
}

@DataProvider
public static Object[][] emailClaims() {
return new Object[][] {{""}, {null}};
}
}

0 comments on commit 1d87137

Please sign in to comment.