Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement custom resolvers for custom auth over oauth2 #11053

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,27 @@
* Interface to use to retrieve
* portal user information.
*/
public interface SecurityRepository {
public interface SecurityRepository<AuthUserContext> {

/**
* Given a user id, returns a user instance.
* If username does not exist in db, returns null.
*
* @param username String
* @param user object that has necessary user information
* @return User
*/
User getPortalUser(String username);
User getPortalUser(String username, AuthUserContext user);

/**
* Given a user id, returns a UserAuthorities instance.
* If username does not exist in db, returns null.
*
* @param username String
* @param user object that has necessary user information
* @return UserAuthorities
*/
UserAuthorities getPortalUserAuthorities(String username);
UserAuthorities getPortalUserAuthorities(String username, AuthUserContext user);

void addPortalUser(User user);
void addPortalUserAuthorities(UserAuthorities userAuthorities);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,4 @@ public interface SecurityMapper {

void addPortalUser(User user);
void addPortalUserAuthority(@Param("email") String email, @Param("authority") String authority);

/**
* Given an internal cancer study id, returns groups string.
* Returns null if cancer study does not exist.
*
* @param internalCancerStudyId Integer
* @return String groups
*/
String getCancerStudyGroups(Integer internalCancerStudyId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,31 @@
import org.cbioportal.model.UserAuthorities;
import org.cbioportal.persistence.SecurityRepository;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class SecurityMyBatisRepository implements SecurityRepository {
@ConditionalOnProperty(name = "security.repository.type", havingValue = "cbioportal", matchIfMissing = true)
public class SecurityMyBatisRepository implements SecurityRepository<Object> {

private static final Logger log = LoggerFactory.getLogger(SecurityMyBatisRepository.class);

@Autowired
private SecurityMapper securityMapper;

@Autowired
private StudyGroupMapper studyGroupMapper;

/**
* Given a user id, returns a user instance.
* If username does not exist in db, returns null.
*
* @param username String
* @param _unused
* @return User
*/
@Override
public User getPortalUser(String username) {
public User getPortalUser(String username, Object _unused) {
User user = securityMapper.getPortalUser(username);
if (user != null) {
log.debug("User " + username + " was found in the users table, email is " + user.getEmail());
Expand All @@ -79,10 +84,11 @@ public User getPortalUser(String username) {
* If username does not exist in db, returns null.
*
* @param username String
* @param _unused
* @return UserAuthorities
*/
@Override
public UserAuthorities getPortalUserAuthorities(String username) {
public UserAuthorities getPortalUserAuthorities(String username, Object _unused) {
return securityMapper.getPortalUserAuthorities(username);
}

Expand All @@ -107,7 +113,7 @@ public void addPortalUserAuthorities(UserAuthorities userAuthorities) {
*/
@Override
public Set<String> getCancerStudyGroups(Integer internalCancerStudyId) {
String groups = securityMapper.getCancerStudyGroups(internalCancerStudyId);
String groups = studyGroupMapper.getCancerStudyGroups(internalCancerStudyId);
if (groups == null) {
return Collections.emptySet();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
* FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder
* is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no
* obligations to provide maintenance, support, updates, enhancements or
* modifications. In no event shall Memorial Sloan-Kettering Cancer Center be
* liable to any party for direct, indirect, special, incidental or
* consequential damages, including lost profits, arising out of the use of this
* software and its documentation, even if Memorial Sloan-Kettering Cancer
* Center has been advised of the possibility of such damage.
*/

/*
* This file is part of cBioPortal.
*
* cBioPortal is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.cbioportal.persistence.mybatis;

// imports
import org.apache.ibatis.annotations.Param;

/**
* Interface to use to retrieve
* portal user information.
*/
public interface StudyGroupMapper {
/**
* Given an internal cancer study id, returns groups string.
* Returns null if cancer study does not exist.
*
* @param internalCancerStudyId Integer
* @return String groups
*/
String getCancerStudyGroups(Integer internalCancerStudyId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;

import java.util.HashSet;
import java.util.Objects;
Expand All @@ -29,12 +30,12 @@
public class CustomOAuth2AuthorizationConfig {
Logger log = LoggerFactory.getLogger(CustomOAuth2AuthorizationConfig.class);

private final SecurityRepository securityRepository;
private final SecurityRepository<OidcUser> securityRepository;

private static final String NAME_ATTRIBUTE_KEY = "email";

@Autowired
public CustomOAuth2AuthorizationConfig(SecurityRepository securityRepository) {
public CustomOAuth2AuthorizationConfig(SecurityRepository<OidcUser> securityRepository) {
this.securityRepository = securityRepository;
}

Expand All @@ -48,9 +49,9 @@ public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
// Delegate to the default implementation for loading a user
OidcUser oidcUser = delegate.loadUser(userRequest);

var authenticatedPortalUser = loadPortalUser(oidcUser.getEmail());
var authenticatedPortalUser = loadPortalUser(oidcUser.getEmail(), oidcUser);
if (Objects.isNull(authenticatedPortalUser.cbioUser) || !authenticatedPortalUser.cbioUser.isEnabled()) {
log.debug("User: {} either not in db or not authorized", oidcUser.getEmail());
log.error("User: {} either not in db or not authorized", oidcUser.getEmail());
throw new OAuth2AuthenticationException("user not authorized");
}
Set<GrantedAuthority> mappedAuthorities = authenticatedPortalUser.authorities;
Expand All @@ -59,11 +60,11 @@ public OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
};
}

private AuthenticatedPortalUser loadPortalUser(String email) {
private AuthenticatedPortalUser loadPortalUser(String username, OidcUser user) {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
User cbioUser = securityRepository.getPortalUser(email);
User cbioUser = securityRepository.getPortalUser(username, user);
if (!Objects.isNull(cbioUser)) {
UserAuthorities authorities = securityRepository.getPortalUserAuthorities(email);
UserAuthorities authorities = securityRepository.getPortalUserAuthorities(username, user);
if (!Objects.isNull(authorities)) {
mappedAuthorities.addAll(AuthorityUtils.createAuthorityList(authorities.getAuthorities()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2015 Memorial Sloan-Kettering Cancer Center.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
* FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder
* is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no
* obligations to provide maintenance, support, updates, enhancements or
* modifications. In no event shall Memorial Sloan-Kettering Cancer Center be
* liable to any party for direct, indirect, special, incidental or
* consequential damages, including lost profits, arising out of the use of this
* software and its documentation, even if Memorial Sloan-Kettering Cancer
* Center has been advised of the possibility of such damage.
*/

/*
* This file is part of cBioPortal.
*
* cBioPortal is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.cbioportal.security.config.access;

// imports
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.cbioportal.model.User;
import org.cbioportal.model.UserAuthorities;
import org.cbioportal.persistence.SecurityRepository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

import org.springframework.stereotype.Service;

@Service
@ConditionalOnProperty(name = "security.repository.type", havingValue = "disabled")
public class FullAccessResolver implements SecurityRepository<Object> {

private static final Logger log = LoggerFactory.getLogger(FullAccessResolver.class);

/**
* Always returns a valid user.
*
* @param username String
* @param user Object
* @return User
*/
@Override
public User getPortalUser(String username, Object user) {
return new User(username, username, true);
}

/**
* Given a user id, returns a UserAuthorities instance.
* If username does not exist in db, returns null.
*
* @param username String
* @param user Object
* @return UserAuthorities
*/
@Override
public UserAuthorities getPortalUserAuthorities(String username, Object user) {
return new UserAuthorities();
}

@Override
public void addPortalUser(User user) {
//no-op
}

@Override
public void addPortalUserAuthorities(UserAuthorities userAuthorities) {
//no-op
}

/**
* Given an internal cancer study id, returns a set of upper case cancer study group strings.
* Returns empty set if cancer study does not exist or there are no groups.
*
* @param internalCancerStudyId Integer
* @return Set<String> cancer study group strings in upper case
*/
@Override
public Set<String> getCancerStudyGroups(Integer internalCancerStudyId) {
return Collections.emptySet();
}
}
Loading