authn refactor

This commit is contained in:
Efstratios Giannopoulos 2023-10-11 17:53:12 +03:00
parent 8b05ee1d0f
commit 968f45d5b3
152 changed files with 1991 additions and 2995 deletions

View File

@ -0,0 +1,35 @@
package eu.eudat.commons.scope;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import javax.management.InvalidApplicationException;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
@Component
@RequestScope
public class UserScope {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserScope.class));
private final AtomicReference<UUID> userId = new AtomicReference<>();
public Boolean isSet() {
return this.userId.get() != null;
}
public UUID getUserId() throws InvalidApplicationException {
if (this.userId.get() == null) throw new InvalidApplicationException("user not set");
return this.userId.get();
}
public UUID getUserIdSafe() {
return this.userId.get();
}
public void setUserId(UUID userId) {
this.userId.set(userId);
}
}

View File

@ -22,6 +22,10 @@
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>dmp-backend</groupId>
<artifactId>queryable</artifactId>

View File

@ -1,16 +0,0 @@
package eu.eudat.data.dao.entities.security;
import eu.eudat.data.dao.DatabaseAccessLayer;
import eu.eudat.data.entities.UserToken;
import java.util.UUID;
public interface UserTokenDao extends DatabaseAccessLayer<UserToken, UUID> {
UserToken createOrUpdate(UserToken item);
UserToken find(UUID id);
void delete(UserToken token);
}

View File

@ -1,51 +0,0 @@
package eu.eudat.data.dao.entities.security;
import eu.eudat.data.dao.DatabaseAccess;
import eu.eudat.data.dao.databaselayer.service.DatabaseService;
import eu.eudat.data.entities.UserToken;
import eu.eudat.queryable.QueryableList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@Component("userTokenDao")
public class UserTokenDaoImpl extends DatabaseAccess<UserToken> implements UserTokenDao {
@Autowired
public UserTokenDaoImpl(DatabaseService<UserToken> databaseService) {
super(databaseService);
}
@Override
public UserToken createOrUpdate(UserToken item) {
return this.getDatabaseService().createOrUpdate(item, UserToken.class);
}
@Override
public UserToken find(UUID id) {
return this.getDatabaseService().getQueryable(UserToken.class).where((builder, root) -> builder.equal(root.get("token"), id)).getSingleOrDefault();
}
@Override
public void delete(UserToken userToken) {
this.getDatabaseService().delete(userToken);
}
@Override
public QueryableList<UserToken> asQueryable() {
return this.getDatabaseService().getQueryable(UserToken.class);
}
@Override
public CompletableFuture<UserToken> createOrUpdateAsync(UserToken item) {
return CompletableFuture.supplyAsync(() -> this.createOrUpdate(item));
}
@Override
public UserToken find(UUID id, String hint) {
throw new UnsupportedOperationException();
}
}

View File

@ -22,33 +22,46 @@ public class Credential implements DataEntity<Credential, UUID> {
@Id
@Column(name = "\"Id\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)")
private UUID id;
public final static String _id = "id";
@ManyToOne
@JoinColumn(name = "\"UserId\"", nullable = false)
private UserInfo userInfo;
public final static String _userInfo = "userInfo"; //TODO: Authn
@Column(name = "\"Status\"", nullable = false)
private Integer status;
public final static String _status = "status";
@Column(name = "\"Provider\"", nullable = false)
private Integer provider;
public final static String _provider = "provider";
@Column(name = "\"Public\"", nullable = false)
private String publicValue;
public final static String _publicValue = "public";
@Column(name = "\"Email\"")
private String email;
public final static String _email = "email";
@Column(name = "\"Secret\"", nullable = false)
private String secret;
public final static String _secret = "secret";
@Column(name = "\"CreationTime\"", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date creationTime;
public final static String _creationTime = "creationTime";
@Column(name = "\"LastUpdateTime\"", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date lastUpdateTime;
public final static String _lastUpdateTime = "lastUpdateTime";
@Column(name = "\"ExternalId\"", nullable = false)
private String externalId;
public final static String _externalId = "externalId";
public UUID getId() {
return id;

View File

@ -24,40 +24,50 @@ public class UserInfo implements DataEntity<UserInfo, UUID> {
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(name = "id", updatable = false, nullable = false, columnDefinition = "BINARY(16)")
private UUID id;
public final static String _id = "id";
@Column(name = "email")
private String email = null;
public final static String _email = "email";
@Column(name = "authorization_level", nullable = false)
private Short authorization_level; //0 admin, 1 user
public final static String _authorization_level = "authorization_level";
@Column(name = "usertype", nullable = false)
private Short usertype; // 0 internal, 1 external
public final static String _usertype = "usertype";
@Column(name = "userstatus", nullable = false)
private Short userStatus; // 0 active, 1 inactive
public final static String _userStatus = "userStatus";
@Column(name = "verified_email", nullable = true)
private Boolean verified_email = null;
public final static String _verified_email = "verified_email";
@Column(name = "name", nullable = true)
private String name = null;
public final static String _name = "name";
@Column(name = "created", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date created = null;
public final static String _created = "created";
@Column(name = "lastloggedin", nullable = true)
@Convert(converter = DateToUTCConverter.class)
private Date lastloggedin = null;
public final static String _lastloggedin = "lastloggedin";
@Type(eu.eudat.configurations.typedefinition.XMLType.class)
@Column(name = "additionalinfo", nullable = true)
private String additionalinfo;
public final static String _additionalinfo = "additionalinfo";
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "\"UserDMP\"",

View File

@ -1,82 +0,0 @@
package eu.eudat.data.entities;
import eu.eudat.data.converters.DateToUTCConverter;
import eu.eudat.data.entities.helpers.EntityBinder;
import eu.eudat.queryable.queryableentity.DataEntity;
import jakarta.persistence.*;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@Entity
@Table(name = "\"UserToken\"")
public class UserToken implements DataEntity<UserToken, UUID> {
@Id
@Column(name = "\"Token\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)")
private UUID token;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "\"UserId\"", nullable = false)
private UserInfo user;
@Column(name = "\"IssuedAt\"", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date issuedAt = null;
@Column(name = "\"ExpiresAt\"", nullable = false)
@Convert(converter = DateToUTCConverter.class)
private Date expiresAt = null;
public UUID getToken() {
return token;
}
public void setToken(UUID token) {
this.token = token;
}
public UserInfo getUser() {
return user;
}
public void setUser(UserInfo user) {
this.user = user;
}
public Date getIssuedAt() {
return issuedAt;
}
public void setIssuedAt(Date issuedAt) {
this.issuedAt = issuedAt;
}
public Date getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(Date expiresAt) {
this.expiresAt = expiresAt;
}
@Override
public void update(UserToken entity) {
}
@Override
public UUID getKeys() {
return this.token;
}
@Override
public UserToken buildFromTuple(List<Tuple> tuple, List<String> fields, String base) {
String currentBase = base.isEmpty() ? "" : base + ".";
if (fields.contains(currentBase + "token")) this.token = EntityBinder.fromTuple(tuple, currentBase + "token");
return this;
}
}

View File

@ -137,6 +137,11 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
@ -304,6 +309,11 @@
</dependency>
<!--CITE DEPENDENCIES-->
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authn</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>data-tools</artifactId>

View File

@ -63,6 +63,10 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<!--<dependency>
@ -117,26 +121,6 @@
<version>3.0.0</version>
</dependency>
<!-- facebook Login -->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-facebook</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<!-- linkedin Login -->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-linkedin</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
<!-- tweeter login-->
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-twitter</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>

View File

@ -1,17 +1,36 @@
package eu.eudat;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import eu.eudat.data.BaseEntity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication(scanBasePackages = {"eu.eudat", "eu.eudat.depositinterface", "gr.cite"})
@SpringBootApplication(scanBasePackages = {
"eu.eudat",
"eu.eudat.depositinterface",
"gr.cite",
"gr.cite.tools",
"gr.cite.commons"
})
@EnableAsync
public class EuDatApplication extends SpringBootServletInitializer {
@Bean
@Primary
public ObjectMapper primaryObjectMapper() {
return JsonMapper.builder().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.addModule(new JavaTimeModule()).build();
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(EuDatApplication.class);

View File

@ -27,7 +27,7 @@ public class ResponsesCache {
@Bean
public CacheManager cacheManager() {
public CacheManager cacheManager5() {
logger.info("Loading ResponsesCache...");
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
List<CaffeineCache> caches = new ArrayList<CaffeineCache>();

View File

@ -0,0 +1,130 @@
package eu.eudat.configurations;
import gr.cite.commons.web.oidc.configuration.WebSecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManagerResolver;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
private final WebSecurityProperties webSecurityProperties;
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
private final Filter apiKeyFilter;
@Autowired
public SecurityConfiguration(WebSecurityProperties webSecurityProperties,
@Qualifier("tokenAuthenticationResolver") AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver,
@Qualifier("apiKeyFilter") Filter apiKeyFilter) {
this.webSecurityProperties = webSecurityProperties;
this.authenticationManagerResolver = authenticationManagerResolver;
this.apiKeyFilter = apiKeyFilter;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
HttpSecurity tempHttp = http
.csrf(AbstractHttpConfigurer::disable)
.cors(httpSecurityCorsConfigurer -> {})
.headers(httpSecurityHeadersConfigurer -> httpSecurityHeadersConfigurer.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.addFilterBefore(apiKeyFilter, AbstractPreAuthenticatedProcessingFilter.class)
.authorizeHttpRequests(authRequest ->
authRequest.requestMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous()
.requestMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated())
.sessionManagement( sessionManagementConfigurer-> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.NEVER))
.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver));
return tempHttp.build();
}
// @Bean
// AuthorizationPolicyConfigurer authorizationPolicyConfigurer() {
// return new AuthorizationPolicyConfigurer() {
//
// @Override
// public AuthorizationPolicyResolverStrategy strategy() {
// return AuthorizationPolicyResolverStrategy.STRICT_CONSENSUS_BASED;
// }
//
// //Here you can register your custom authorization handlers, which will get used as well as the existing ones
// //This is optional and can be omitted
// //If not set / set to null, only the default authorization handlers will be used
// @Override
// public List<AuthorizationHandler<? extends AuthorizationRequirement>> addCustomHandlers() {
// return null;
// }
//
// //Here you can register your custom authorization requirements (if any)
// //This is optional and can be omitted
// //If not set / set to null, only the default authorization requirements will be used
// @Override
// public List<? extends AuthorizationRequirement> extendRequirements() {
// return List.of(
//// new TimeOfDayAuthorizationRequirement(new TimeOfDay("08:00","16:00"), true)
// );
// }
//
// //Here you can select handlers you want to disable by providing the classes they are implemented by
// //You can disable any handler (including any custom one)
// //This is optional and can be omitted
// //If not set / set to null, all the handlers will be invoked, based on their requirement support
// //In the example below, the default client handler will be ignored by the resolver
// @Override
// public List<Class<? extends AuthorizationHandler<? extends AuthorizationRequirement>>> disableHandlers() {
// return List.of(PermissionClientAuthorizationHandler.class);
// }
// };
// }
//
// @Bean
// AuthorizationRequirementMapper authorizationRequirementMapper() {
// return new AuthorizationRequirementMapper() {
// @Override
// public AuthorizationRequirement map(AuthorizationResource resource, boolean matchAll, String[] permissions) {
// Class<?> type = resource.getClass();
// if (!AuthorizationResource.class.isAssignableFrom(type)) throw new IllegalArgumentException("resource");
//
// if (OwnedResource.class.equals(type)) {
// return new OwnedAuthorizationRequirement();
// }
// throw new IllegalArgumentException("resource");
// }
// };
// }
private String[] buildAntPatterns(Set<String> endpoints) {
if (endpoints == null) {
return new String[0];
}
return endpoints.stream()
.filter(endpoint -> endpoint != null && !endpoint.isBlank())
.map(endpoint -> "/" + stripUnnecessaryCharacters(endpoint) + "/**")
.toArray(String[]::new);
}
private String stripUnnecessaryCharacters(String endpoint) {
endpoint = endpoint.strip();
if (endpoint.startsWith("/")) {
endpoint = endpoint.substring(1);
}
if (endpoint.endsWith("/")) {
endpoint = endpoint.substring(0, endpoint.length() - 1);
}
return endpoint;
}
}

View File

@ -1,9 +1,11 @@
package eu.eudat.configurations;
import eu.eudat.controllers.interceptors.RequestInterceptor;
import eu.eudat.commons.scope.UserScope;
import eu.eudat.interceptors.UserInterceptor;
import eu.eudat.logic.handlers.PrincipalArgumentResolver;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@ -23,22 +25,29 @@ public class WebMVCConfiguration implements WebMvcConfigurer {
private AuthenticationService verifiedUserAuthenticationService;
private AuthenticationService nonVerifiedUserAuthenticationService;
private final UserInterceptor userInterceptor;
private final UserScope userScope;
private final CurrentPrincipalResolver currentPrincipalResolver;
@Autowired
public WebMVCConfiguration(ApiContext apiContext, AuthenticationService verifiedUserAuthenticationService, AuthenticationService nonVerifiedUserAuthenticationService) {
public WebMVCConfiguration(ApiContext apiContext, AuthenticationService verifiedUserAuthenticationService, AuthenticationService nonVerifiedUserAuthenticationService, UserInterceptor userInterceptor, UserScope userScope, CurrentPrincipalResolver currentPrincipalResolver) {
this.apiContext = apiContext;
this.verifiedUserAuthenticationService = verifiedUserAuthenticationService;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.userInterceptor = userInterceptor;
this.userScope = userScope;
this.currentPrincipalResolver = currentPrincipalResolver;
}
@Autowired
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new PrincipalArgumentResolver(verifiedUserAuthenticationService, nonVerifiedUserAuthenticationService));
argumentResolvers.add(new PrincipalArgumentResolver(verifiedUserAuthenticationService, nonVerifiedUserAuthenticationService, userScope, currentPrincipalResolver));
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(new RequestInterceptor(this.apiContext.getHelpersService().getLoggerService()));
registry.addWebRequestInterceptor(userInterceptor).order(1);
}
}

View File

@ -3,8 +3,6 @@ package eu.eudat.controllers;
import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException;
import eu.eudat.exceptions.emailconfirmation.TokenExpiredException;
import eu.eudat.logic.managers.EmailConfirmationManager;
import eu.eudat.logic.security.CustomAuthenticationProvider;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.ApiMessageCode;
@ -17,7 +15,7 @@ import jakarta.transaction.Transactional;
@RestController
@CrossOrigin
@RequestMapping(value = "api/emailConfirmation")
@RequestMapping(value = "/api/emailConfirmation/")
public class EmailConfirmation {
private EmailConfirmationManager emailConfirmationManager;

View File

@ -2,10 +2,7 @@ package eu.eudat.controllers;
import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException;
import eu.eudat.exceptions.emailconfirmation.TokenExpiredException;
import eu.eudat.logic.managers.EmailConfirmationManager;
import eu.eudat.logic.managers.MergeEmailConfirmationManager;
import eu.eudat.logic.security.CustomAuthenticationProvider;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal;
import eu.eudat.models.data.userinfo.UserMergeRequestModel;

View File

@ -1,53 +1,17 @@
package eu.eudat.controllers;
import eu.eudat.exceptions.security.ExpiredTokenException;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.managers.MetricsManager;
import eu.eudat.logic.managers.UserManager;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.security.CustomAuthenticationProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.models.ConfigurableProvidersModel;
import eu.eudat.logic.security.validators.b2access.B2AccessTokenValidator;
import eu.eudat.logic.security.validators.b2access.helpers.B2AccessRequest;
import eu.eudat.logic.security.validators.b2access.helpers.B2AccessResponseToken;
import eu.eudat.logic.security.validators.configurableProvider.ConfigurableProviderTokenValidator;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderRequest;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderResponseToken;
import eu.eudat.logic.security.validators.linkedin.LinkedInTokenValidator;
import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInRequest;
import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInResponseToken;
import eu.eudat.logic.security.validators.openaire.OpenAIRETokenValidator;
import eu.eudat.logic.security.validators.openaire.helpers.OpenAIRERequest;
import eu.eudat.logic.security.validators.openaire.helpers.OpenAIREResponseToken;
import eu.eudat.logic.security.validators.orcid.ORCIDTokenValidator;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDRequest;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
import eu.eudat.logic.security.validators.twitter.TwitterTokenValidator;
import eu.eudat.logic.security.validators.zenodo.ZenodoTokenValidator;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoRequest;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoResponseToken;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.login.Credentials;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.principal.PrincipalModel;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.ApiMessageCode;
import eu.eudat.types.MetricNames;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.social.oauth1.OAuthToken;
import org.springframework.web.bind.annotation.*;
import jakarta.transaction.Transactional;
import java.io.IOException;
import java.security.GeneralSecurityException;
@RestController
@CrossOrigin
@ -55,122 +19,12 @@ import java.security.GeneralSecurityException;
public class Login {
private static final Logger logger = LoggerFactory.getLogger(Login.class);
private CustomAuthenticationProvider customAuthenticationProvider;
private AuthenticationService nonVerifiedUserAuthenticationService;
private TwitterTokenValidator twitterTokenValidator;
private B2AccessTokenValidator b2AccessTokenValidator;
private ORCIDTokenValidator orcidTokenValidator;
private LinkedInTokenValidator linkedInTokenValidator;
private OpenAIRETokenValidator openAIRETokenValidator;
private ConfigurableProviderTokenValidator configurableProviderTokenValidator;
private ZenodoTokenValidator zenodoTokenValidator;
private ConfigLoader configLoader;
private final MetricsManager metricsManager;
// private Logger logger;
private UserManager userManager;
@Autowired
public Login(CustomAuthenticationProvider customAuthenticationProvider,
AuthenticationService nonVerifiedUserAuthenticationService, TwitterTokenValidator twitterTokenValidator,
B2AccessTokenValidator b2AccessTokenValidator, ORCIDTokenValidator orcidTokenValidator,
LinkedInTokenValidator linkedInTokenValidator, OpenAIRETokenValidator openAIRETokenValidator,
ConfigurableProviderTokenValidator configurableProviderTokenValidator, ZenodoTokenValidator zenodoTokenValidator,
ConfigLoader configLoader, UserManager userManager,
MetricsManager metricsManager) {
this.customAuthenticationProvider = customAuthenticationProvider;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.twitterTokenValidator = twitterTokenValidator;
this.b2AccessTokenValidator = b2AccessTokenValidator;
this.orcidTokenValidator = orcidTokenValidator;
this.linkedInTokenValidator = linkedInTokenValidator;
this.openAIRETokenValidator = openAIRETokenValidator;
this.configurableProviderTokenValidator = configurableProviderTokenValidator;
this.zenodoTokenValidator = zenodoTokenValidator;
public Login(
ConfigLoader configLoader) {
this.configLoader = configLoader;
this.userManager = userManager;
this.metricsManager = metricsManager;
}
@Transactional
@RequestMapping(method = RequestMethod.POST, value = {"/externallogin"}, consumes = "application/json", produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<PrincipalModel>> externallogin(@RequestBody LoginInfo credentials) throws GeneralSecurityException, NullEmailException {
logger.info("Trying To Login With " + credentials.getProvider());
metricsManager.increaseValue(MetricNames.USERS, 1, MetricNames.LOGGEDIN);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<PrincipalModel>().payload(customAuthenticationProvider.authenticate(credentials)).status(ApiMessageCode.SUCCESS_MESSAGE));
}
@Transactional
@RequestMapping(method = RequestMethod.POST, value = {"/nativelogin"}, consumes = "application/json", produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<PrincipalModel>> nativelogin(@RequestBody Credentials credentials) throws NullEmailException {
logger.info(credentials.getUsername() + " Trying To Login");
metricsManager.increaseValue(MetricNames.USERS, 1, MetricNames.LOGGEDIN);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<PrincipalModel>().payload(userManager.authenticate(this.nonVerifiedUserAuthenticationService, credentials)).status(ApiMessageCode.SUCCESS_MESSAGE));
}
@RequestMapping(method = RequestMethod.GET, value = {"/twitterRequestToken"}, produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<OAuthToken>> twitterRequestToken() {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<OAuthToken>().payload(this.twitterTokenValidator.getRequestToken()).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/linkedInRequestToken"}, produces = "application/json", consumes = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<LinkedInResponseToken>> linkedInRequestToken(@RequestBody LinkedInRequest linkedInRequest) {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<LinkedInResponseToken>().payload(this.linkedInTokenValidator.getAccessToken(linkedInRequest)).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/b2AccessRequestToken"}, produces = "application/json", consumes = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<B2AccessResponseToken>> b2AccessRequestToken(@RequestBody B2AccessRequest b2AccessRequest) {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<B2AccessResponseToken>().payload(this.b2AccessTokenValidator.getAccessToken(b2AccessRequest)).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/orcidRequestToken"}, produces = "application/json", consumes = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<ORCIDResponseToken>> ORCIDRequestToken(@RequestBody ORCIDRequest orcidRequest) {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<ORCIDResponseToken>().payload(this.orcidTokenValidator.getAccessToken(orcidRequest)).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/openAireRequestToken"}, produces = "application/json", consumes = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<OpenAIREResponseToken>> openAIRERequestToken(@RequestBody OpenAIRERequest openAIRERequest) {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<OpenAIREResponseToken>().payload(this.openAIRETokenValidator.getAccessToken(openAIRERequest)).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/configurableProviderRequestToken"}, produces = "application/json", consumes = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<ConfigurableProviderResponseToken>> configurableProviderRequestToken(@RequestBody ConfigurableProviderRequest configurableProviderRequest) {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<ConfigurableProviderResponseToken>().payload(this.configurableProviderTokenValidator.getAccessToken(configurableProviderRequest)).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/zenodoRequestToken"}, produces = "application/json", consumes = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<ZenodoResponseToken>> ZenodoRequestToken(@RequestBody ZenodoRequest zenodoRequest) {
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<ZenodoResponseToken>().payload(this.zenodoTokenValidator.getAccessToken(zenodoRequest)).status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.POST, value = {"/me"}, consumes = "application/json", produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<PrincipalModel>> authMe(Principal principal) throws NullEmailException {
logger.info(principal + " Getting Me");
Principal principal1 = this.nonVerifiedUserAuthenticationService.Touch(principal.getToken());
PrincipalModel principalModel = PrincipalModel.fromEntity(principal1);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<PrincipalModel>().payload(principalModel).status(ApiMessageCode.NO_MESSAGE));
}
@Transactional
@RequestMapping(method = RequestMethod.POST, value = {"/logout"}, consumes = "application/json", produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<Principal>> logout(Principal principal) {
this.nonVerifiedUserAuthenticationService.Logout(principal.getToken());
logger.info(principal + " Logged Out");
metricsManager.decreaseValue(MetricNames.USERS, 1, MetricNames.LOGGEDIN);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Principal>().status(ApiMessageCode.NO_MESSAGE));
}
@RequestMapping(method = RequestMethod.GET, value = {"/configurableLogin"}, consumes = "application/json", produces = "application/json")

View File

@ -1,52 +0,0 @@
package eu.eudat.controllers;
import eu.eudat.logic.security.CustomAuthenticationProvider;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.principal.PrincipalModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@CrossOrigin
@RequestMapping(value = {"/api/auth/saml2"})
public class Saml2PostBinding extends BaseController {
private CustomAuthenticationProvider customAuthenticationProvider;
@Autowired
public Saml2PostBinding(ApiContext apiContext, CustomAuthenticationProvider customAuthenticationProvider) {
super(apiContext);
this.customAuthenticationProvider = customAuthenticationProvider;
}
@RequestMapping(method = RequestMethod.POST, value = {"/postBinding"}, consumes = "application/x-www-form-urlencoded")
public @ResponseBody
ResponseEntity<Void> verify(@RequestParam(value = "SAMLResponse") String SAMLResponse, @RequestParam(value = "RelayState") String RelayState) throws GeneralSecurityException {
Map<String, String> map = Arrays.stream(RelayState.split("&")).map(s -> s.split("=")).collect(Collectors.toMap(e -> e[0], e -> e[1]));
LoginInfo loginInfo = new LoginInfo();
loginInfo.setTicket(SAMLResponse);
loginInfo.setProvider(TokenValidatorFactoryImpl.LoginProvider.CONFIGURABLE.getValue());
Map<String, String> providerId = new HashMap<>();
providerId.put("configurableLoginId", map.get("configurableLoginId"));
loginInfo.setData(providerId);
PrincipalModel principal = this.customAuthenticationProvider.authenticate(loginInfo);
return ResponseEntity.status(HttpStatus.FOUND).header(HttpHeaders.LOCATION, "http://localhost:4200/login/external/saml?token=" + principal.getToken().toString()).build();
}
}

View File

@ -0,0 +1,71 @@
package eu.eudat.controllers.v2;
import eu.eudat.models.data.dataset.DatasetOverviewModel;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.v2.AccountBuilder;
import eu.eudat.types.ApiMessageCode;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import eu.eudat.models.v2.Account;
@RestController
@CrossOrigin
@RequestMapping(value = { "/api/principal/" })
public class PrincipalController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrincipalController.class));
private final AuditService auditService;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final AccountBuilder accountBuilder;
@Autowired
public PrincipalController(
CurrentPrincipalResolver currentPrincipalResolver,
AccountBuilder accountBuilder,
AuditService auditService) {
this.currentPrincipalResolver = currentPrincipalResolver;
this.accountBuilder = accountBuilder;
this.auditService = auditService;
}
@RequestMapping(path = "me", method = RequestMethod.GET )
public ResponseEntity<?> me(FieldSet fieldSet) {
logger.debug("me");
if (fieldSet == null || fieldSet.isEmpty()) {
fieldSet = new BaseFieldSet(
Account._isAuthenticated,
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._subject),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._userId),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._name),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._scope),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._client),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._issuedAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._notBefore),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._authenticatedAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._expiresAt),
BaseFieldSet.asIndexer(Account._principal, Account.PrincipalInfo._more),
Account._roles);
}
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
Account me = this.accountBuilder.build(fieldSet, principal);
//this.auditService.track(AuditableAction.Principal_Lookup);
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Account>().status(ApiMessageCode.NO_MESSAGE).payload(me));
}
}

View File

@ -0,0 +1,245 @@
package eu.eudat.interceptors;
import eu.eudat.commons.scope.UserScope;
import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.types.Authorities;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Tuple;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;
import javax.management.InvalidApplicationException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
@Component
public class UserInterceptor implements WebRequestInterceptor {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UserInterceptor.class));
private final UserScope userScope;
private final ClaimExtractor claimExtractor;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final PlatformTransactionManager transactionManager;
private final UserInterceptorCacheService userInterceptorCacheService;
@PersistenceContext
public EntityManager entityManager;
@Autowired
public UserInterceptor(
UserScope userScope,
ClaimExtractor claimExtractor,
CurrentPrincipalResolver currentPrincipalResolver,
PlatformTransactionManager transactionManager,
UserInterceptorCacheService userInterceptorCacheService
) {
this.userScope = userScope;
this.currentPrincipalResolver = currentPrincipalResolver;
this.claimExtractor = claimExtractor;
this.transactionManager = transactionManager;
this.userInterceptorCacheService = userInterceptorCacheService;
}
@Override
public void preHandle(WebRequest request) throws InvalidApplicationException {
UUID userId = null;
if (this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) {
String subjectId = this.claimExtractor.subjectString(this.currentPrincipalResolver.currentPrincipal());
UserInterceptorCacheService.UserInterceptorCacheValue cacheValue = this.userInterceptorCacheService.lookup(this.userInterceptorCacheService.buildKey(subjectId));
if (cacheValue != null) {
userId = cacheValue.getUserId();
} else {
userId = this.getUserIdFromDatabaseBySubject(subjectId);
if (userId == null ) {
String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal());
if (email != null && !email.isBlank()) {
userId = this.getUserIdFromDatabaseByEmail(email);
userId = this.createOrUpdateUser(subjectId, userId);
} else {
boolean checkMailNull = ((ServletWebRequest) request).getRequest().getServletPath().toLowerCase(Locale.ROOT).startsWith("/api/emailConfirmation".toLowerCase(Locale.ROOT));
if (!checkMailNull) throw new NullEmailException();
}
}
if (userId != null) this.userInterceptorCacheService.put(new UserInterceptorCacheService.UserInterceptorCacheValue(subjectId, userId));
}
}
this.userScope.setUserId(userId);
}
private UUID getUserIdFromDatabaseBySubject(String subjectId) {
CriteriaBuilder credentialCriteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> credentialQuery = credentialCriteriaBuilder.createQuery(Tuple.class);
Root<Credential> credentialRoot = credentialQuery.from(Credential.class);
credentialQuery.where(
credentialCriteriaBuilder.and(
credentialCriteriaBuilder.equal(credentialRoot.get(Credential._externalId), subjectId),
credentialCriteriaBuilder.equal(credentialRoot.get(Credential._status), 1), //TODO: Authn
credentialCriteriaBuilder.equal(credentialRoot.get(Credential._provider), 128)
));
credentialQuery.multiselect(credentialRoot.get(Credential._userInfo).get(UserInfo._id).alias(UserInfo._id));
List<Tuple> results = this.entityManager.createQuery(credentialQuery).getResultList();
return this.getUUIDFromTuple(results, UserInfo._id);
}
private UUID getUserIdFromDatabaseByEmail(String email) {
CriteriaBuilder emailCriteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> emailQuery = emailCriteriaBuilder.createQuery(Tuple.class);
Root<UserInfo> emailRoot = emailQuery.from(UserInfo.class);
emailQuery.where(
emailCriteriaBuilder.and(
emailCriteriaBuilder.equal(emailRoot.get(UserInfo._email), email),
emailCriteriaBuilder.equal(emailRoot.get(UserInfo._userStatus), 0) //TODO: Authn
));
emailQuery.multiselect(emailRoot.get(UserInfo._id).alias(UserInfo._id));
List<Tuple> results = this.entityManager.createQuery(emailQuery).getResultList();
return this.getUUIDFromTuple(results, UserInfo._id);
}
private UUID getUUIDFromTuple(List<Tuple> results, String field){
if (results.size() > 0) {//TODO: Authn
Object o;
try {
o = results.get(0).get(field);
} catch (IllegalArgumentException e) {
return null;
}
if (o == null) return null;
try {
return UUID.class.cast(o);
} catch (ClassCastException e) {
return null;
}
}
return null;
}
private UUID createOrUpdateUser(String subjectId, UUID userId) {
String name = this.claimExtractor.name(this.currentPrincipalResolver.currentPrincipal());
String emailVerified = this.claimExtractor.emailVerified(this.currentPrincipalResolver.currentPrincipal());
String email = this.claimExtractor.email(this.currentPrincipalResolver.currentPrincipal());
if (name == null) name = subjectId;
UserInfo user = null;
UserRole userRole = null;
boolean isUpdateUser = userId != null;
if (!isUpdateUser) {
user = new UserInfo();
user.setId(UUID.randomUUID());
user.setVerified_email("true".equals(emailVerified));//TODO: Authn
user.setName(name);
user.setEmail(email);
user.setCreated(new Date());
user.setLastloggedin(new Date());
user.setLastloggedin(new Date());
user.setAuthorization_level((short) 1);//TODO: Authn
user.setUsertype((short) 1);
user.setUserStatus((short) 0);
// user.setAdditionalinfo("{\"data\":{\"avatar\":{\"url\":\"" + profile.getAvatarUrl()
// + "\"},\"zenodoToken\":\"" + profile.getZenodoId()
// + "\", \"expirationDate\": \"" + Instant.now().plusSeconds((profile.getZenodoExpire() != null ? profile.getZenodoExpire(): 0)).toEpochMilli()
// + "\", \"zenodoRefresh\": \"" + profile.getZenodoRefresh()
// + (profile.getProvider() == TokenValidatorFactoryImpl.LoginProvider.ZENODO ? "\", \"zenodoEmail\": \"" + profile.getEmail() : "") +"\"}}");
user.setAdditionalinfo("{\"data\":{\"avatar\":{\"url\":\"\"},\"zenodoToken\":\"\", \"expirationDate\": \"\", \"zenodoRefresh\": \"\", \"zenodoEmail\": \"\"}}"); //TODO: Authn
userRole = new UserRole();
userRole.setId(UUID.randomUUID());
userRole.setUserInfo(user);
userRole.setRole(Authorities.USER.getValue());
} else {
CriteriaBuilder emailCriteriaBuilder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<UserInfo> userQuery = emailCriteriaBuilder.createQuery(UserInfo.class);
Root<UserInfo> userRoot = userQuery.from(UserInfo.class);
userQuery.where(
emailCriteriaBuilder.and(
emailCriteriaBuilder.equal(userRoot.get(UserInfo._id), userId),
emailCriteriaBuilder.equal(userRoot.get(UserInfo._userStatus), 0) //TODO: Authn
));
userQuery.select(userRoot);
TypedQuery<UserInfo> q = this.entityManager.createQuery(userQuery);
List<UserInfo> userInfos = q.getResultList();
if (userInfos == null || userInfos.size() < 1) {
throw new MyApplicationException("Can not found user " + userId);
}
user = userInfos.get(0);
user.setAdditionalinfo("{\"data\":{\"avatar\":{\"url\":\"\"},\"zenodoToken\":\"\", \"expirationDate\": \"\", \"zenodoRefresh\": \"\", \"zenodoEmail\": \"\"}}"); //TODO: Authn
}
Credential credential = new Credential();
credential.setId(UUID.randomUUID());
credential.setUserInfo(user);
credential.setSecret(subjectId);
credential.setCreationTime(new Date());
credential.setLastUpdateTime(new Date());
credential.setStatus(1);
credential.setProvider(128);//TODO: Authn
credential.setExternalId(subjectId);
credential.setEmail(email);
credential.setPublicValue(email);
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setName(UUID.randomUUID().toString());
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = null;
try {
status = transactionManager.getTransaction(definition);
if (!isUpdateUser) {
user = this.entityManager.merge(user);
this.entityManager.flush();
userRole.setUserInfo(user);
credential.setUserInfo(user);
this.entityManager.merge(userRole);
this.entityManager.merge(credential);
} else {
this.entityManager.persist(user);
this.entityManager.persist(credential);
}
this.entityManager.flush();
transactionManager.commit(status);
} catch (Exception ex) {
if (status != null) transactionManager.rollback(status);
throw ex;
}
return user.getId();
}
@Override
public void postHandle(@NonNull WebRequest request, ModelMap model) {
this.userScope.setUserId(null);
}
@Override
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
}
}

View File

@ -0,0 +1,10 @@
package eu.eudat.interceptors;
import gr.cite.tools.cache.CacheOptions;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "cache.user-by-subject-id")
public class UserInterceptorCacheOptions extends CacheOptions {
}

View File

@ -0,0 +1,78 @@
package eu.eudat.interceptors;
import eu.eudat.convention.ConventionService;
import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.UUID;
@Service
public class UserInterceptorCacheService extends CacheService<UserInterceptorCacheService.UserInterceptorCacheValue> {
public static class UserInterceptorCacheValue {
public UserInterceptorCacheValue() {
}
public UserInterceptorCacheValue(String subjectId, UUID userId) {
this.subjectId = subjectId;
this.userId = userId;
}
private String subjectId;
public String getSubjectId() {
return subjectId;
}
public void setSubjectId(String subjectId) {
this.subjectId = subjectId;
}
private UUID userId;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
}
private final ConventionService conventionService;
@Autowired
public UserInterceptorCacheService(UserInterceptorCacheOptions options, ConventionService conventionService) {
super(options);
this.conventionService = conventionService;
}
// @EventListener //TODO: Authn
// public void handleUserTouchedEvent(UserTouchedEvent event) {
// if (!this.conventionService.isNullOrEmpty(event.getSubjectId()))
// this.evict(this.buildKey(event.getSubjectId()));
// if (!this.conventionService.isNullOrEmpty(event.getPreviousSubjectId()))
// this.evict(this.buildKey(event.getPreviousSubjectId()));
// }
@Override
protected Class<UserInterceptorCacheValue> valueClass() {
return UserInterceptorCacheValue.class;
}
@Override
public String keyOf(UserInterceptorCacheValue value) {
return this.buildKey(value.getSubjectId());
}
public String buildKey(String subject) {
HashMap<String, String> keyParts = new HashMap<>();
keyParts.put("$subject$", subject);
return this.generateKey(keyParts);
}
}

View File

@ -24,7 +24,6 @@ public class BuilderFactoryImpl implements BuilderFactory {
if (tClass.equals(RegistryCriteriaBuilder.class)) return (T) new RegistryCriteriaBuilder();
if (tClass.equals(UserInfoBuilder.class)) return (T) new UserInfoBuilder();
if (tClass.equals(UserRoleBuilder.class)) return (T) new UserRoleBuilder();
if (tClass.equals(UserTokenBuilder.class)) return (T) new UserTokenBuilder();
if (tClass.equals(ResearcherBuilder.class)) return (T) new ResearcherBuilder();
if (tClass.equals(ExternalDatasetCriteriaBuilder.class)) return (T) new ExternalDatasetCriteriaBuilder();
if (tClass.equals(RecentActivityDataBuilder.class)) return (T) new RecentActivityDataBuilder();

View File

@ -1,52 +0,0 @@
package eu.eudat.logic.builders.entity;
import eu.eudat.logic.builders.Builder;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserToken;
import java.util.Date;
import java.util.UUID;
/**
* Created by ikalyvas on 2/15/2018.
*/
public class UserTokenBuilder extends Builder<UserToken> {
private UUID token;
private UserInfo user;
private Date issuedAt;
private Date expiresAt;
public UserTokenBuilder token(UUID token) {
this.token = token;
return this;
}
public UserTokenBuilder user(UserInfo user) {
this.user = user;
return this;
}
public UserTokenBuilder issuedAt(Date issuedAt) {
this.issuedAt = issuedAt;
return this;
}
public UserTokenBuilder expiresAt(Date expiresAt) {
this.expiresAt = expiresAt;
return this;
}
@Override
public UserToken build() {
UserToken userToken = new UserToken();
userToken.setExpiresAt(expiresAt);
userToken.setToken(token);
userToken.setUser(user);
userToken.setIssuedAt(issuedAt);
return userToken;
}
}

View File

@ -1,12 +1,13 @@
package eu.eudat.logic.handlers;
import eu.eudat.commons.scope.UserScope;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.Authorities;
import org.apache.catalina.connector.RequestFacade;
import org.apache.tomcat.util.buf.MessageBytes;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
@ -14,6 +15,7 @@ import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.management.InvalidApplicationException;
import java.lang.annotation.Annotation;
import java.util.*;
@ -22,10 +24,14 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
private AuthenticationService verifiedUserAuthenticationService;
private AuthenticationService nonVerifiedUserAuthenticationService;
private final UserScope userScope;
private final CurrentPrincipalResolver currentPrincipalResolver;
public PrincipalArgumentResolver(AuthenticationService verifiedUserAuthenticationService, AuthenticationService nonVerifiedUserAuthenticationService) {
public PrincipalArgumentResolver(AuthenticationService verifiedUserAuthenticationService, AuthenticationService nonVerifiedUserAuthenticationService, UserScope userScope, CurrentPrincipalResolver currentPrincipalResolver) {
this.verifiedUserAuthenticationService = verifiedUserAuthenticationService;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.userScope = userScope;
this.currentPrincipalResolver = currentPrincipalResolver;
}
@Override
@ -35,7 +41,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
String token = nativeWebRequest.getHeader("AuthToken");
MyPrincipal claimsPrincipal = this.currentPrincipalResolver.currentPrincipal();
boolean checkMailNull = ((ServletWebRequest) nativeWebRequest).getRequest().getRequestURI().startsWith("/api/emailConfirmation");
AuthenticationService authenticationService = checkMailNull ? this.nonVerifiedUserAuthenticationService : this.verifiedUserAuthenticationService;
@ -44,18 +50,24 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
List<Authorities> claimList = claimsAnnotation.map(annotation -> Arrays.asList(((ClaimedAuthorities) annotation).claims())).orElse(Authorities.all());
if (claimList.size() == 1 && claimList.get(0).equals(Authorities.ANONYMOUS)) {
return new Principal();
} else if (claimList.contains(Authorities.ANONYMOUS) && token == null) {
} else if (claimList.contains(Authorities.ANONYMOUS) && !claimsPrincipal.isAuthenticated()) {
return new Principal();
}
if (token == null) throw new UnauthorisedException("Authentication Information Is Missing");
UUID authToken;
if (!claimsPrincipal.isAuthenticated()) throw new UnauthorisedException("Authentication Information Is Missing");
Principal principal;
if (checkMailNull){
principal = authenticationService.Touch(claimsPrincipal);
} else {
UUID userId;
try{
authToken = UUID.fromString(token);
} catch (IllegalArgumentException ex) {
userId = checkMailNull ? null : this.userScope.getUserId();
} catch (InvalidApplicationException e) {
throw new UnauthorisedException("Authentication Information Is Missing");
}
Principal principal = authenticationService.Touch(authToken);
principal = authenticationService.Touch(userId);
}
if (principal == null) throw new UnauthorisedException("Authentication Information Missing");
if (!claimList.contains(Authorities.ANONYMOUS) && !principal.isAuthorized(claimList))
throw new UnauthorisedException("You are not Authorized For this Action");

View File

@ -3,14 +3,11 @@ package eu.eudat.logic.managers;
import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.EmailConfirmation;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserToken;
import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException;
import eu.eudat.exceptions.emailconfirmation.TokenExpiredException;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.models.data.security.Principal;
import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.jpa.predicates.OrderByPredicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -53,7 +50,7 @@ public class EmailConfirmationManager {
databaseRepository.getCredentialDao().createOrUpdate(credential);
UserInfo oldUser = databaseRepository.getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), loginConfirmationEmail.getEmail())).getSingle();
mergeNewUserToOld(user, oldUser);
expireUserToken(user);
// expireUserToken(user); //TODO: Authn
databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail);
return;
}
@ -87,14 +84,4 @@ public class EmailConfirmationManager {
credential.setUserInfo(oldUser);
databaseRepository.getCredentialDao().createOrUpdate(credential);
}
private void expireUserToken(UserInfo user) {
UserToken userToken = databaseRepository.getUserTokenDao().asQueryable()
.where((builder, root) -> builder.equal(root.get("user"), user))
.orderBy((builder, root) -> builder.desc(root.get("issuedAt")))
.take(1)
.getSingle();
userToken.setExpiresAt(new Date());
databaseRepository.getUserTokenDao().createOrUpdate(userToken);
}
}

View File

@ -4,7 +4,6 @@ import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.EmailConfirmation;
import eu.eudat.data.entities.UserDMP;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserToken;
import eu.eudat.elastic.criteria.DmpCriteria;
import eu.eudat.elastic.entities.Collaborator;
import eu.eudat.elastic.entities.Dmp;
@ -14,23 +13,17 @@ import eu.eudat.exceptions.emailconfirmation.TokenExpiredException;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.models.data.security.Principal;
import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.jpa.predicates.OrderByPredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.transaction.Transactional;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
public class MergeEmailConfirmationManager {
@ -66,7 +59,7 @@ public class MergeEmailConfirmationManager {
// Checks if mail is used by another user. If it is, merges the new the old.
mergeNewUserToOld(user, userToBeMerged, Integer.valueOf((String) map.get("provider")));
expireUserToken(userToBeMerged);
//expireUserToken(userToBeMerged); //TODO: Authn
loginConfirmationEmail.setIsConfirmed(true);
databaseRepository.getLoginConfirmationEmailDao().createOrUpdate(loginConfirmationEmail);
} catch (Exception e) {
@ -143,13 +136,4 @@ public class MergeEmailConfirmationManager {
});
databaseRepository.getUserInfoDao().createOrUpdate(oldUser);
}
private void expireUserToken(UserInfo user) {
UserToken userToken = databaseRepository.getUserTokenDao().asQueryable()
.where((builder, root) -> builder.equal(root.get("user"), user))
.orderBy((builder, root) -> builder.desc(root.get("issuedAt")))
.take(1).toList().get(0);
userToken.setExpiresAt(new Date());
databaseRepository.getUserTokenDao().createOrUpdate(userToken);
}
}

View File

@ -5,10 +5,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.EmailConfirmation;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserToken;
import eu.eudat.exceptions.emailconfirmation.HasConfirmedEmailException;
import eu.eudat.exceptions.emailconfirmation.TokenExpiredException;
import eu.eudat.logic.builders.entity.UserTokenBuilder;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.models.data.security.Principal;
@ -18,10 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import jakarta.transaction.Transactional;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class UnlinkEmailConfirmationManager {

View File

@ -133,13 +133,6 @@ public class UserManager {
.createOrUpdate(userInfo);
}
public PrincipalModel authenticate(AuthenticationService authenticationServiceImpl, Credentials credentials) throws NullEmailException {
Principal principal = authenticationServiceImpl.Touch(credentials);
if (principal == null) throw new UnauthorisedException("Could not Sign In User");
PrincipalModel principalModel = PrincipalModel.fromEntity(principal);
return principalModel;
}
public DataTableData<UserListingModel> getCollaboratorsPaged(UserInfoTableRequestItem userInfoTableRequestItem, Principal principal) throws Exception {
UserInfoDao userInfoDao = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao();
QueryableList<UserInfo> users = userInfoDao.getWithCriteria(userInfoTableRequestItem.getCriteria());
@ -154,7 +147,7 @@ public class UserManager {
return dataTableData;
}
public void registerDOIToken(DOIRequest doiRequest, Principal principal) throws IOException {
public void registerDOIToken(DOIRequest doiRequest, Principal principal) throws IOException { //TODO: Authn
ZenodoResponseToken responseToken = this.zenodoCustomProvider.getAccessToken(ZenodoAccessType.AUTHORIZATION_CODE,
doiRequest.getZenodoRequest().getCode(), this.environment.getProperty("zenodo.login.client_id"),
this.environment.getProperty("zenodo.login.client_secret"), doiRequest.getRedirectUri());
@ -219,8 +212,9 @@ public class UserManager {
return new UserProfile().fromDataModel(user);
}
public Long countActiveUsers(){
return apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().asQueryable().where(((builder, root) -> builder.greaterThan(root.get("expiresAt"), new Date()))).count();
public Long countActiveUsers(){ //TODO: Authn
return 0L;
//return apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().asQueryable().where(((builder, root) -> builder.greaterThan(root.get("expiresAt"), new Date()))).count();
}
public Long countAllUsers(){

View File

@ -1,47 +0,0 @@
package eu.eudat.logic.security;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.principal.PrincipalModel;
import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.security.validators.TokenValidatorFactory;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
@Component
public class CustomAuthenticationProvider {
private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
@Autowired
private TokenValidatorFactory tokenValidatorFactory;
public PrincipalModel authenticate(LoginInfo credentials) throws GeneralSecurityException, NullEmailException {
String token = credentials.getTicket();
try {
Principal principal = this.tokenValidatorFactory.getProvider(credentials.getProvider()).validateToken(credentials);
return (principal != null) ? PrincipalModel.fromEntity(principal) : null;
} catch (NonValidTokenException e) {
logger.error("Could not validate a user by his token! Reason: " + e.getMessage(), e);
throw new UnauthorisedException("Token validation failed - Not a valid token");
} catch (IOException e) {
logger.error(e.getMessage(), e);
throw new UnauthorisedException("IO Exeption");
} catch (NullEmailException e) {
logger.error(e.getMessage(), e);
throw new NullEmailException();
} catch (ResolverException | ComponentInitializationException e){
logger.error(e.getMessage(), e);
throw new GeneralSecurityException();
}
}
}

View File

@ -1,12 +0,0 @@
package eu.eudat.logic.security.customproviders.B2Access;
import eu.eudat.logic.security.validators.b2access.helpers.B2AccessResponseToken;
/**
* Created by ikalyvas on 2/22/2018.
*/
public interface B2AccessCustomProvider {
B2AccessUser getUser(String accessToken);
B2AccessResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret);
}

View File

@ -1,76 +0,0 @@
package eu.eudat.logic.security.customproviders.B2Access;
import eu.eudat.logic.security.validators.b2access.helpers.B2AccessResponseToken;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.Map;
@Component("b2AccessCustomProvider")
public class B2AccessCustomProviderImpl implements B2AccessCustomProvider {
private Environment environment;
@Autowired
public B2AccessCustomProviderImpl(Environment environment) {
this.environment = environment;
}
public B2AccessUser getUser(String accessToken) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = this.createBearerAuthHeaders(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
Map<String, Object> values = restTemplate.exchange(this.environment.getProperty("b2access.externallogin.user_info_url"), HttpMethod.GET, entity, Map.class).getBody();
B2AccessUser b2AccessUser = new B2AccessUser();
b2AccessUser.setEmail((String)values.get("email"));
b2AccessUser.setId((String)values.get("urn:oid:2.5.4.49"));
b2AccessUser.setName((String)values.get("name"));
return b2AccessUser;
}
@Override
public B2AccessResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret) {
RestTemplate template = new RestTemplate();
HttpHeaders headers = this.createBasicAuthHeaders(clientId, clientSecret);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("code", code);
map.add("grant_type", "authorization_code");
map.add("redirect_uri", redirectUri);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
Map<String, Object> values = template.postForObject(this.environment.getProperty("b2access.externallogin.access_token_url"), request, Map.class);
B2AccessResponseToken b2AccessResponseToken = new B2AccessResponseToken();
b2AccessResponseToken.setAccessToken((String) values.get("access_token"));
return b2AccessResponseToken;
}
private HttpHeaders createBasicAuthHeaders(String username, String password) {
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")));
String authHeader = "Basic " + new String(encodedAuth);
set("Authorization", authHeader);
}};
}
private HttpHeaders createBearerAuthHeaders(String accessToken) {
return new HttpHeaders() {{
String authHeader = "Bearer " + new String(accessToken);
set("Authorization", authHeader);
}};
}
}

View File

@ -1,34 +0,0 @@
package eu.eudat.logic.security.customproviders.B2Access;
/**
* Created by ikalyvas on 2/22/2018.
*/
public class B2AccessUser {
private String id;
private String name;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -1,11 +0,0 @@
package eu.eudat.logic.security.customproviders.ConfigurableProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.oauth2.Oauth2ConfigurableProviderUserSettings;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderResponseToken;
public interface ConfigurableProviderCustomProvider {
ConfigurableProviderResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret, String accessTokenUrl, String grantType, String access_token, String expires_in);
ConfigurableProviderUser getUser(String accessToken, Oauth2ConfigurableProviderUserSettings user);
}

View File

@ -1,61 +0,0 @@
package eu.eudat.logic.security.customproviders.ConfigurableProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.oauth2.Oauth2ConfigurableProviderUserSettings;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderResponseToken;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Component("configurableProviderCustomProvider")
public class ConfigurableProviderCustomProviderImpl implements ConfigurableProviderCustomProvider {
@Override
public ConfigurableProviderResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret, String accessTokenUrl,
String grantType, String access_token, String expires_in) {
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("grant_type", grantType);
map.add("code", code);
map.add("redirect_uri", redirectUri);
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
Map<String, Object> values = template.postForObject(accessTokenUrl, request, Map.class);
ConfigurableProviderResponseToken responseToken = new ConfigurableProviderResponseToken();
responseToken.setAccessToken((String) values.get(access_token));
if (expires_in != null && !expires_in.isEmpty()) {
responseToken.setExpiresIn((Integer) values.get(expires_in));
}
return responseToken;
}
@Override
public ConfigurableProviderUser getUser(String accessToken, Oauth2ConfigurableProviderUserSettings user) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = this.createBearerAuthHeaders(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
Map<String, Object> values = restTemplate.exchange(user.getUser_info_url(), HttpMethod.GET, entity, Map.class).getBody();
return new ConfigurableProviderUser().getConfigurableProviderUser(values, user);
}
private HttpHeaders createBearerAuthHeaders(String accessToken) {
return new HttpHeaders() {{
String authHeader = "Bearer " + accessToken;
set("Authorization", authHeader);
}};
}
}

View File

@ -1,42 +0,0 @@
package eu.eudat.logic.security.customproviders.ConfigurableProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.oauth2.Oauth2ConfigurableProviderUserSettings;
import java.util.Map;
public class ConfigurableProviderUser {
private String id;
private String name;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
ConfigurableProviderUser getConfigurableProviderUser(Map data, Oauth2ConfigurableProviderUserSettings user) {
if (user.getId() != null && !user.getId().isEmpty())
this.id = (String) data.get(user.getId());
if (user.getName() != null && !user.getName().isEmpty())
this.name = (String) data.get(user.getName());
if (user.getEmail() != null && !user.getEmail().isEmpty())
this.email = (String) data.get(user.getEmail());
return this;
}
}

View File

@ -1,10 +0,0 @@
package eu.eudat.logic.security.customproviders.LinkedIn;
import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInResponseToken;
public interface LinkedInCustomProvider {
LinkedInUser getUser(String accessToken);
LinkedInResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret);
}

View File

@ -1,67 +0,0 @@
package eu.eudat.logic.security.customproviders.LinkedIn;
import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInResponseToken;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Component("LinkedInCustomProvider")
public class LinkedInCustomProviderImpl implements LinkedInCustomProvider {
private Environment environment;
public LinkedInCustomProviderImpl(Environment environment) {
this.environment = environment;
}
public LinkedInUser getUser(String accessToken) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = this.createBearerAuthHeaders(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
Map profileValues = restTemplate.exchange(this.environment.getProperty("linkedin.login.user_info_url"), HttpMethod.GET, entity, Map.class).getBody();
Map emailValues = restTemplate.exchange(this.environment.getProperty("linkedin.login.user_email"), HttpMethod.GET, entity, Map.class).getBody();
LinkedInUser linkedInUser = new LinkedInUser();
linkedInUser.setEmail((String)emailValues.get("email"));
linkedInUser.setName((String)profileValues.get("localizedFirstName"));
linkedInUser.setId((String)profileValues.get("id"));
return linkedInUser;
}
public LinkedInResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret) {
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("grant_type", "authorization_code");
map.add("code", code);
map.add("redirect_uri", redirectUri);
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
Map<String, Object> values = template.postForObject(this.environment.getProperty("linkedin.login.access_token_url"), request, Map.class);
LinkedInResponseToken linkedInResponseToken = new LinkedInResponseToken();
linkedInResponseToken.setAccessToken((String) values.get("access_token"));
linkedInResponseToken.setExpiresIn((Integer) values.get("expires_in"));
return linkedInResponseToken;
}
private HttpHeaders createBearerAuthHeaders(String accessToken) {
return new HttpHeaders() {{
String authHeader = "Bearer " + new String(accessToken);
set("Authorization", authHeader);
}};
}
}

View File

@ -1,29 +0,0 @@
package eu.eudat.logic.security.customproviders.LinkedIn;
public class LinkedInUser {
private String id;
private String name;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -1,7 +0,0 @@
package eu.eudat.logic.security.customproviders.ORCID;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
public interface ORCIDCustomProvider {
ORCIDResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret);
}

View File

@ -1,54 +0,0 @@
package eu.eudat.logic.security.customproviders.ORCID;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Component("ORCIDCustomProvider")
public class ORCIDCustomProviderImpl implements ORCIDCustomProvider {
private Environment environment;
@Autowired
public ORCIDCustomProviderImpl(Environment environment) {
this.environment = environment;
}
@Override
public ORCIDResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("accept", "application/json");
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("client_id", this.environment.getProperty("orcid.login.client_id"));
map.add("client_secret", this.environment.getProperty("orcid.login.client_secret"));
map.add("grant_type", "authorization_code");
map.add("code", code);
map.add("redirect_uri", redirectUri);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
Map<String, Object> values = restTemplate.postForObject(this.environment.getProperty("orcid.login.access_token_url"), request, Map.class);
ORCIDResponseToken orcidResponseToken = new ORCIDResponseToken();
orcidResponseToken.setOrcidId((String) values.get("orcid"));
orcidResponseToken.setName((String) values.get("name"));
orcidResponseToken.setAccessToken((String) values.get("access_token"));
return orcidResponseToken;
}
private HttpHeaders createBearerAuthHeaders(String accessToken) {
return new HttpHeaders() {{
String authHeader = "Bearer " + accessToken;
set("Authorization", authHeader);
}};
}
}

View File

@ -1,38 +0,0 @@
package eu.eudat.logic.security.customproviders.ORCID;
import java.util.Map;
public class ORCIDUser {
private String orcidId;
private String name;
private String email;
public String getOrcidId() {
return orcidId;
}
public void setOrcidId(String orcidId) {
this.orcidId = orcidId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public ORCIDUser getOrcidUser(Object data) {
this.orcidId = (String) ((Map) data).get("orcidId");
this.name = (String) ((Map) data).get("name");
this.email = (String) ((Map) data).get("email");
return this;
}
}

View File

@ -1,10 +0,0 @@
package eu.eudat.logic.security.customproviders.OpenAIRE;
import eu.eudat.logic.security.validators.openaire.helpers.OpenAIREResponseToken;
public interface OpenAIRECustomProvider {
OpenAIREResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret);
OpenAIREUser getUser(String accessToken);
}

View File

@ -1,62 +0,0 @@
package eu.eudat.logic.security.customproviders.OpenAIRE;
import eu.eudat.logic.security.validators.openaire.helpers.OpenAIREResponseToken;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Component("openAIRECustomProvider")
public class OpenAIRECustomProviderImpl implements OpenAIRECustomProvider {
private Environment environment;
public OpenAIRECustomProviderImpl(Environment environment) {
this.environment = environment;
}
public OpenAIREUser getUser(String accessToken) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = this.createBearerAuthHeaders(accessToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
Map<String, Object> values = restTemplate.exchange(this.environment.getProperty("openaire.login.user_info_url"), HttpMethod.GET, entity, Map.class).getBody();
return new OpenAIREUser().getOpenAIREUser(values);
}
public OpenAIREResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret) {
RestTemplate template = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("grant_type", "authorization_code");
map.add("code", code);
map.add("redirect_uri", redirectUri);
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
Map<String, Object> values = template.postForObject(this.environment.getProperty("openaire.login.access_token_url"), request, Map.class);
OpenAIREResponseToken openAIREResponseToken = new OpenAIREResponseToken();
openAIREResponseToken.setAccessToken((String) values.get("access_token"));
openAIREResponseToken.setExpiresIn((Integer) values.get("expires_in"));
return openAIREResponseToken;
}
private HttpHeaders createBearerAuthHeaders(String accessToken) {
return new HttpHeaders() {{
String authHeader = "Bearer " + accessToken;
set("Authorization", authHeader);
}};
}
}

View File

@ -1,37 +0,0 @@
package eu.eudat.logic.security.customproviders.OpenAIRE;
import java.util.Map;
public class OpenAIREUser {
private String id;
private String name;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public OpenAIREUser getOpenAIREUser(Object data) {
this.id = (String) ((Map) data).get("sub");
this.name = (String) ((Map) data).get("name");
this.email = (String) ((Map) data).get("email");
return this;
}
}

View File

@ -1,6 +1,5 @@
package eu.eudat.logic.security.customproviders.Zenodo;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoResponseToken;
public interface ZenodoCustomProvider {

View File

@ -1,7 +1,5 @@
package eu.eudat.logic.security.customproviders.Zenodo;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoResponseToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -1,17 +0,0 @@
package eu.eudat.logic.security.validators;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.security.Principal;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import java.io.IOException;
import java.security.GeneralSecurityException;
public interface TokenValidator {
Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException, NullEmailException, ResolverException, ComponentInitializationException;
}

View File

@ -1,6 +0,0 @@
package eu.eudat.logic.security.validators;
public interface TokenValidatorFactory {
TokenValidator getProvider(TokenValidatorFactoryImpl.LoginProvider provider);
}

View File

@ -1,120 +0,0 @@
package eu.eudat.logic.security.validators;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.security.customproviders.B2Access.B2AccessCustomProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.ConfigurableProviderCustomProvider;
import eu.eudat.logic.security.customproviders.LinkedIn.LinkedInCustomProvider;
import eu.eudat.logic.security.customproviders.ORCID.ORCIDCustomProvider;
import eu.eudat.logic.security.customproviders.OpenAIRE.OpenAIRECustomProvider;
import eu.eudat.logic.security.customproviders.Zenodo.ZenodoCustomProvider;
import eu.eudat.logic.security.validators.b2access.B2AccessTokenValidator;
import eu.eudat.logic.security.validators.configurableProvider.ConfigurableProviderTokenValidator;
import eu.eudat.logic.security.validators.facebook.FacebookTokenValidator;
import eu.eudat.logic.security.validators.google.GoogleTokenValidator;
import eu.eudat.logic.security.validators.linkedin.LinkedInTokenValidator;
import eu.eudat.logic.security.validators.openaire.OpenAIRETokenValidator;
import eu.eudat.logic.security.validators.orcid.ORCIDTokenValidator;
import eu.eudat.logic.security.validators.twitter.TwitterTokenValidator;
import eu.eudat.logic.security.validators.zenodo.ZenodoTokenValidator;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Service("tokenValidatorFactory")
public class TokenValidatorFactoryImpl implements TokenValidatorFactory {
public enum LoginProvider {
GOOGLE(1), FACEBOOK(2), TWITTER(3), LINKEDIN(4), NATIVELOGIN(5), B2_ACCESS(6), ORCID(7), OPENAIRE(8), CONFIGURABLE(9), ZENODO(10);
private int value;
private LoginProvider(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static LoginProvider fromInteger(int value) {
switch (value) {
case 1:
return GOOGLE;
case 2:
return FACEBOOK;
case 3:
return TWITTER;
case 4:
return LINKEDIN;
case 5:
return NATIVELOGIN;
case 6:
return B2_ACCESS;
case 7:
return ORCID;
case 8:
return OPENAIRE;
case 9:
return CONFIGURABLE;
case 10:
return ZENODO;
default:
throw new RuntimeException("Unsupported LoginProvider");
}
}
}
private Environment environment;
private AuthenticationService nonVerifiedUserAuthenticationService;
private B2AccessCustomProvider b2AccessCustomProvider;
private ORCIDCustomProvider orcidCustomProvider;
private LinkedInCustomProvider linkedInCustomProvider;
private OpenAIRECustomProvider openAIRECustomProvider;
private ConfigurableProviderCustomProvider configurableProviderCustomProvider;
private ConfigLoader configLoader;
private ZenodoCustomProvider zenodoCustomProvider;
@Autowired
public TokenValidatorFactoryImpl(
Environment environment,
AuthenticationService nonVerifiedUserAuthenticationService, B2AccessCustomProvider b2AccessCustomProvider,
ORCIDCustomProvider orcidCustomProvider, LinkedInCustomProvider linkedInCustomProvider, OpenAIRECustomProvider openAIRECustomProvider,
ConfigurableProviderCustomProvider configurableProviderCustomProvider, ConfigLoader configLoader,
ZenodoCustomProvider zenodoCustomProvider) {
this.environment = environment;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.b2AccessCustomProvider = b2AccessCustomProvider;
this.orcidCustomProvider = orcidCustomProvider;
this.linkedInCustomProvider = linkedInCustomProvider;
this.openAIRECustomProvider = openAIRECustomProvider;
this.configurableProviderCustomProvider = configurableProviderCustomProvider;
this.configLoader = configLoader;
this.zenodoCustomProvider = zenodoCustomProvider;
}
public TokenValidator getProvider(LoginProvider provider) {
switch (provider) {
case GOOGLE:
return new GoogleTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService);
case FACEBOOK:
return new FacebookTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService);
case LINKEDIN:
return new LinkedInTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, linkedInCustomProvider);
case TWITTER:
return new TwitterTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService);
case B2_ACCESS:
return new B2AccessTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.b2AccessCustomProvider);
case ORCID:
return new ORCIDTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.orcidCustomProvider);
case OPENAIRE:
return new OpenAIRETokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.openAIRECustomProvider);
case CONFIGURABLE:
return new ConfigurableProviderTokenValidator(this.configurableProviderCustomProvider, this.nonVerifiedUserAuthenticationService, this.configLoader);
case ZENODO:
return new ZenodoTokenValidator(this.environment, this.nonVerifiedUserAuthenticationService, this.zenodoCustomProvider);
default:
throw new RuntimeException("Login Provider Not Implemented");
}
}
}

View File

@ -1,52 +0,0 @@
package eu.eudat.logic.security.validators.b2access;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.security.customproviders.B2Access.B2AccessCustomProvider;
import eu.eudat.logic.security.customproviders.B2Access.B2AccessUser;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.b2access.helpers.B2AccessRequest;
import eu.eudat.logic.security.validators.b2access.helpers.B2AccessResponseToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
@Component("b2AccessTokenValidator ")
public class B2AccessTokenValidator implements TokenValidator {
private B2AccessCustomProvider b2AccessCustomProvider;
private AuthenticationService nonVerifiedUserAuthenticationService;
private Environment environment;
@Autowired
public B2AccessTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService, B2AccessCustomProvider b2AccessCustomProvider) {
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.environment = environment;
this.b2AccessCustomProvider = b2AccessCustomProvider;
}
@Override
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException, NullEmailException {
B2AccessUser b2AccessUser = this.b2AccessCustomProvider.getUser(credentials.getTicket());
LoginProviderUser user = new LoginProviderUser();
user.setId(b2AccessUser.getId());
user.setEmail(b2AccessUser.getEmail());
user.setName(b2AccessUser.getName());
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
public B2AccessResponseToken getAccessToken(B2AccessRequest b2AccessRequest) {
return this.b2AccessCustomProvider.getAccessToken(b2AccessRequest.getCode(), this.environment.getProperty("b2access.externallogin.redirect_uri")
, this.environment.getProperty("b2access.externallogin.clientid")
, this.environment.getProperty("b2access.externallogin.clientSecret"));
}
}

View File

@ -1,16 +0,0 @@
package eu.eudat.logic.security.validators.b2access.helpers;
/**
* Created by ikalyvas on 2/22/2018.
*/
public class B2AccessRequest {
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@ -1,16 +0,0 @@
package eu.eudat.logic.security.validators.b2access.helpers;
/**
* Created by ikalyvas on 2/22/2018.
*/
public class B2AccessResponseToken {
private String accessToken;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}

View File

@ -1,139 +0,0 @@
package eu.eudat.logic.security.validators.configurableProvider;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.ConfigurableProviderCustomProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.ConfigurableProviderUser;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.oauth2.Oauth2ConfigurableProvider;
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.saml2.Saml2ConfigurableProvider;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderRequest;
import eu.eudat.logic.security.validators.configurableProvider.helpers.ConfigurableProviderResponseToken;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.opensaml.saml.saml2.core.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component("configurableProviderTokenValidator")
public class ConfigurableProviderTokenValidator implements TokenValidator {
private static final Logger logger = LoggerFactory.getLogger(ConfigurableProviderTokenValidator.class);
private ConfigurableProviderCustomProvider configurableProvider;
private AuthenticationService nonVerifiedUserAuthenticationService;
private ConfigLoader configLoader;
public ConfigurableProviderTokenValidator(ConfigurableProviderCustomProvider configurableProvider, AuthenticationService nonVerifiedUserAuthenticationService, ConfigLoader configLoader) {
this.configurableProvider = configurableProvider;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.configLoader = configLoader;
}
public ConfigurableProviderResponseToken getAccessToken(ConfigurableProviderRequest configurableProviderRequest) {
Oauth2ConfigurableProvider provider = (Oauth2ConfigurableProvider)getConfigurableProviderFromId(configurableProviderRequest.getConfigurableLoginId());
return this.configurableProvider.getAccessToken(configurableProviderRequest.getCode(),
provider.getRedirect_uri(), provider.getClientId(), provider.getClientSecret(),
provider.getAccess_token_url(), provider.getGrant_type(), provider.getToken().getAccess_token(), provider.getToken().getExpires_in());
}
@Override
public Principal validateToken(LoginInfo credentials) throws NullEmailException {
String configurableLoginId = ((Map) credentials.getData()).get("configurableLoginId").toString();
ConfigurableProvider configurableProvider = getConfigurableProviderFromId(configurableLoginId);
LoginProviderUser user = new LoginProviderUser();
if (configurableProvider.getType().equals("oauth2")) {
ConfigurableProviderUser configurableUser = this.configurableProvider.getUser(credentials.getTicket(), ((Oauth2ConfigurableProvider)configurableProvider).getUser());
user.setId(configurableUser.getId());
user.setEmail(configurableUser.getEmail());
user.setName(configurableUser.getName());
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
else if (configurableProvider.getType().equals("saml2")) {
Assertion saml2Assertion = null;
try {
Saml2ConfigurableProvider saml2Provider = (Saml2ConfigurableProvider)configurableProvider;
if(saml2Provider.getBinding().equals("Redirect") || saml2Provider.getBinding().equals("Post"))
saml2Assertion = Saml2SSOUtils.processResponse(credentials.getTicket(), saml2Provider);
else if(saml2Provider.getBinding().equals("Artifact"))
saml2Assertion = Saml2SSOUtils.processArtifactResponse(credentials.getTicket(), saml2Provider);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
if(saml2Assertion == null)
return null;
List<AttributeStatement> attributeStatements = saml2Assertion.getAttributeStatements();
if(attributeStatements != null && !attributeStatements.isEmpty()){
List<Attribute> attributes = attributeStatements.get(0).getAttributes();
if(attributes != null && !attributes.isEmpty()){
Saml2ConfigurableProvider.SAML2UsingFormat usingFormat = ((Saml2ConfigurableProvider)configurableProvider).getUsingFormat();
Map<String, String> attributeMapping = ((Saml2ConfigurableProvider)configurableProvider).getConfigurableUserFromAttributes();
Map<String, Saml2ConfigurableProvider.SAML2AttributeType> attributeType = ((Saml2ConfigurableProvider)configurableProvider).getAttributeTypes();
Map<String, Object> saml2User = new HashMap<>();
for(Attribute attribute: attributes){
String attributeName = Saml2SSOUtils.getAttributeName(attribute, usingFormat);
if(attributeName != null && attributeMapping.containsValue(attributeName)){
Saml2ConfigurableProvider.SAML2AttributeType attrType = attributeType.get(attributeName);
if(attribute.getAttributeValues() != null && !attribute.getAttributeValues().isEmpty() && attrType != null){
Object attributeValue = Saml2SSOUtils.getAttributeType(attribute.getAttributeValues().get(0), attrType);
if(attributeValue != null) {
saml2User.put(attributeName, attributeValue);
}
}
}
}
try{
String subjectNameId = saml2Assertion.getSubject().getNameID().getValue();
String userId = configurableLoginId + ": " + subjectNameId;
user.setId(userId);
} catch(NullPointerException e){
logger.error("Could not get Subject NameID value of assertion");
return null;
}
user.setEmail((String)saml2User.get(attributeMapping.get("email")));
user.setName((String)saml2User.get(attributeMapping.get("name")));
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
}
}
else
return null;
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
return null;
}
private ConfigurableProvider getConfigurableProviderFromId(String configurableId) {
return this.configLoader.getConfigurableProviders().getProviders().stream()
.filter(prov -> prov.getConfigurableLoginId().equals(configurableId))
.collect(Collectors.toList())
.get(0);
}
}

View File

@ -1,20 +0,0 @@
package eu.eudat.logic.security.validators.configurableProvider.helpers;
public class ConfigurableProviderRequest {
private String code;
private String configurableLoginId;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getConfigurableLoginId() {
return configurableLoginId;
}
public void setConfigurableLoginId(String configurableLoginId) {
this.configurableLoginId = configurableLoginId;
}
}

View File

@ -1,20 +0,0 @@
package eu.eudat.logic.security.validators.configurableProvider.helpers;
public class ConfigurableProviderResponseToken {
private String accessToken;
private Integer expiresIn;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public Integer getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Integer expiresIn) {
this.expiresIn = expiresIn;
}
}

View File

@ -1,65 +0,0 @@
package eu.eudat.logic.security.validators.facebook;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.social.facebook.api.User;
import org.springframework.social.facebook.connect.FacebookServiceProvider;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
@Component("facebookTokenValidator")
public class FacebookTokenValidator implements TokenValidator {
private AuthenticationService nonVerifiedUserAuthenticationService;
private FacebookServiceProvider facebookServiceProvider;
@Autowired
public FacebookTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService) {
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.facebookServiceProvider = new FacebookServiceProvider(environment.getProperty("facebook.login.clientId"), environment.getProperty("facebook.login.clientSecret"), environment.getProperty("facebook.login.namespace"));
}
@Override
public Principal validateToken(LoginInfo credentials) {
User profile = getFacebookUser(credentials.getTicket());
LoginProviderUser user = new LoginProviderUser();
if (profile.getEmail() == null)
throw new UnauthorisedException("Cannot login user.Facebook account did not provide email");
user.setEmail(profile.getEmail());
user.setId(profile.getId());
//user.setIsVerified(profile.isVerified());
user.setName(profile.getName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.FACEBOOK);
String url = (String) ((Map<String, Object>) ((Map<String, Object>) profile.getExtraData().get("picture")).get("data")).get("url");
user.setAvatarUrl(url);
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
private User getFacebookUser(String accessToken) {
String[] fields = {"id", "email", "first_name", "last_name", "name", "verified", "picture"};
return this.facebookServiceProvider.getApi(accessToken).fetchObject("me", User.class, fields);
}
private Date addADay(Date date) {
Date dt = new Date();
Calendar c = Calendar.getInstance();
c.setTime(dt);
c.add(Calendar.DATE, 1);
dt = c.getTime();
return dt;
}
}

View File

@ -1,55 +0,0 @@
package eu.eudat.logic.security.validators.google;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
@Component("googleTokenValidator")
public class GoogleTokenValidator implements TokenValidator {
private static final HttpTransport transport = new NetHttpTransport();
private AuthenticationService nonVerifiedUserAuthenticationService;
private GoogleIdTokenVerifier verifier;
@Autowired
public GoogleTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService) {
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
verifier = new GoogleIdTokenVerifier.Builder(transport, GsonFactory.getDefaultInstance())
.setAudience(Collections.singletonList(environment.getProperty("google.login.clientId")))
.build();
}
private GoogleIdToken verifyUserAndGetUser(String idTokenString) throws IOException, GeneralSecurityException {
return verifier.verify(idTokenString);
}
@Override
public eu.eudat.models.data.security.Principal validateToken(LoginInfo credentials) throws IOException, GeneralSecurityException {
GoogleIdToken idToken = this.verifyUserAndGetUser(credentials.getTicket());
Payload payload = idToken.getPayload();
LoginProviderUser user = new LoginProviderUser();
user.setAvatarUrl((String) payload.get("picture"));
user.setSecret(credentials.getTicket());
user.setId(payload.getSubject());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.GOOGLE);
user.setName((String) payload.get("name"));
user.setEmail(payload.getEmail());
user.setIsVerified(payload.getEmailVerified());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
}

View File

@ -1,67 +0,0 @@
package eu.eudat.logic.security.validators.linkedin;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.logic.security.customproviders.LinkedIn.LinkedInCustomProvider;
import eu.eudat.logic.security.customproviders.LinkedIn.LinkedInUser;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInRequest;
import eu.eudat.logic.security.validators.linkedin.helpers.LinkedInResponseToken;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component("linkedInTokenValidator")
public class LinkedInTokenValidator implements TokenValidator {
private Environment environment;
private AuthenticationService nonVerifiedUserAuthenticationService;
private LinkedInCustomProvider linkedInCustomProvider;
@Autowired
public LinkedInTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService, LinkedInCustomProvider linkedInCustomProvider) {
this.environment = environment;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.linkedInCustomProvider = linkedInCustomProvider;
}
@Override
public Principal validateToken(LoginInfo credentials) {
/*AccessGrant accessGrant = this.linkedInServiceProvider.getOAuthOperations().exchangeForAccess(credentials.getTicket(), this.environment.getProperty("linkedin.login.redirect_uri"), null);
LinkedIn linkedInService = this.linkedInServiceProvider.getApi(accessGrant.getAccessToken());
LinkedInProfile linkedInProfile = linkedInService.profileOperations().getUserProfile();
LoginProviderUser user = new LoginProviderUser();
if (linkedInProfile.getEmailAddress() == null)
throw new UnauthorisedException("Cannot login user.LinkedIn account did not provide email");
user.setEmail(linkedInProfile.getEmailAddress());
user.setId(linkedInProfile.getId());
user.setIsVerified(true); //TODO
user.setAvatarUrl(linkedInProfile.getProfilePictureUrl());
user.setName(linkedInProfile.getFirstName() + " " + linkedInProfile.getLastName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.LINKEDIN);
user.setSecret(accessGrant.getAccessToken());*/
LinkedInUser linkedInUser = this.linkedInCustomProvider.getUser(credentials.getTicket());
if (linkedInUser.getEmail() == null)
throw new UnauthorisedException("Cannot login user.LinkedIn account did not provide email");
LoginProviderUser user = new LoginProviderUser();
user.setId(linkedInUser.getId());
user.setName(linkedInUser.getName());
user.setEmail(linkedInUser.getEmail());
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
public LinkedInResponseToken getAccessToken(LinkedInRequest linkedInRequest) {
return this.linkedInCustomProvider.getAccessToken(
linkedInRequest.getCode(), this.environment.getProperty("linkedin.login.redirect_uri"),
this.environment.getProperty("linkedin.login.clientId"), this.environment.getProperty("linkedin.login.clientSecret"));
}
}

View File

@ -1,12 +0,0 @@
package eu.eudat.logic.security.validators.linkedin.helpers;
public class LinkedInRequest {
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@ -1,21 +0,0 @@
package eu.eudat.logic.security.validators.linkedin.helpers;
public class LinkedInResponseToken {
private String accessToken;
private Integer expiresIn;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public Integer getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Integer expiresIn) {
this.expiresIn = expiresIn;
}
}

View File

@ -1,52 +0,0 @@
package eu.eudat.logic.security.validators.openaire;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.security.customproviders.OpenAIRE.OpenAIRECustomProvider;
import eu.eudat.logic.security.customproviders.OpenAIRE.OpenAIREUser;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.openaire.helpers.OpenAIRERequest;
import eu.eudat.logic.security.validators.openaire.helpers.OpenAIREResponseToken;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
@Component("openAIRETokenValidator")
public class OpenAIRETokenValidator implements TokenValidator {
private Environment environment;
private AuthenticationService nonVerifiedUserAuthenticationService;
private OpenAIRECustomProvider openAIRECustomProvider;
public OpenAIRETokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService, OpenAIRECustomProvider openAIRECustomProvider) {
this.environment = environment;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.openAIRECustomProvider = openAIRECustomProvider;
}
public OpenAIREResponseToken getAccessToken(OpenAIRERequest openAIRERequest) {
return this.openAIRECustomProvider.getAccessToken(
openAIRERequest.getCode(), this.environment.getProperty("openaire.login.redirect_uri"),
this.environment.getProperty("openaire.login.client_id"), this.environment.getProperty("openaire.login.client_secret")
);
}
@Override
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException, NullEmailException {
OpenAIREUser openAIREUser = this.openAIRECustomProvider.getUser(credentials.getTicket());
LoginProviderUser user = new LoginProviderUser();
user.setId(openAIREUser.getId());
user.setEmail(openAIREUser.getEmail());
user.setName(openAIREUser.getName());
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
}

View File

@ -1,12 +0,0 @@
package eu.eudat.logic.security.validators.openaire.helpers;
public class OpenAIRERequest {
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@ -1,20 +0,0 @@
package eu.eudat.logic.security.validators.openaire.helpers;
public class OpenAIREResponseToken {
private String accessToken;
private Integer expiresIn;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public Integer getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(Integer expiresIn) {
this.expiresIn = expiresIn;
}
}

View File

@ -1,51 +0,0 @@
package eu.eudat.logic.security.validators.orcid;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.security.customproviders.ORCID.ORCIDCustomProvider;
import eu.eudat.logic.security.customproviders.ORCID.ORCIDUser;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDRequest;
import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
@Component("orcidTokenValidator")
public class ORCIDTokenValidator implements TokenValidator {
private ORCIDCustomProvider orcidCustomProvider;
private Environment environment;
private AuthenticationService nonVerifiedUserAuthenticationService;
@Autowired
public ORCIDTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService, ORCIDCustomProvider orcidCustomProvider) {
this.environment = environment;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.orcidCustomProvider = orcidCustomProvider;
}
@Override
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException, NullEmailException {
ORCIDUser orcidUser = new ORCIDUser().getOrcidUser(credentials.getData());
LoginProviderUser user = new LoginProviderUser();
user.setId(orcidUser.getOrcidId());
user.setName(orcidUser.getName());
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
public ORCIDResponseToken getAccessToken(ORCIDRequest orcidRequest) {
return this.orcidCustomProvider.getAccessToken(orcidRequest.getCode(), this.environment.getProperty("orcid.login.redirect_uri")
, this.environment.getProperty("orcid.login.client_id")
, this.environment.getProperty("orcid.login.client_secret"));
}
}

View File

@ -1,12 +0,0 @@
package eu.eudat.logic.security.validators.orcid.helpers;
public class ORCIDRequest {
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}

View File

@ -1,28 +0,0 @@
package eu.eudat.logic.security.validators.orcid.helpers;
public class ORCIDResponseToken {
private String orcidId;
private String name;
private String accessToken;
public String getOrcidId() {
return orcidId;
}
public void setOrcidId(String orcidId) {
this.orcidId = orcidId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}

View File

@ -1,74 +0,0 @@
package eu.eudat.logic.security.validators.twitter;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.social.oauth1.AuthorizedRequestToken;
import org.springframework.social.oauth1.OAuthToken;
import org.springframework.social.twitter.api.TwitterProfile;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.social.twitter.connect.TwitterServiceProvider;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Map;
@Component("twitterTokenValidator")
public class TwitterTokenValidator implements TokenValidator {
private Environment environment;
private AuthenticationService nonVerifiedUserAuthenticationService;
private TwitterServiceProvider twitterServiceProvider;
@Autowired
public TwitterTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService) {
this.environment = environment;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.twitterServiceProvider = new TwitterServiceProvider(this.environment.getProperty("twitter.login.clientId"), this.environment.getProperty("twitter.login.clientSecret"));
}
@Override
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException, NullEmailException {
String verifier = (String) ((Map)credentials.getData()).get("verifier");
String email = (String) ((Map) credentials.getData()).get("email");
OAuthToken oAuthToken = new OAuthToken(credentials.getTicket(), verifier);
AuthorizedRequestToken authorizedRequestToken = new AuthorizedRequestToken(oAuthToken, verifier);
OAuthToken finalOauthToken = this.twitterServiceProvider.getOAuthOperations().exchangeForAccessToken(authorizedRequestToken, null);
TwitterTemplate twitterTemplate = new TwitterTemplate(this.environment.getProperty("twitter.login.clientId"), this.environment.getProperty("twitter.login.clientSecret"), finalOauthToken.getValue(), finalOauthToken.getSecret());
TwitterProfile profile = this.twitterServiceProvider.getApi(finalOauthToken.getValue(), finalOauthToken.getSecret()).userOperations().getUserProfile();
LoginProviderUser user = new LoginProviderUser();
Map values = twitterTemplate.getRestTemplate().getForObject("https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true", Map.class);
if (values.get("email") == null) {
// throw new UnauthorisedException("Cannot login user.Twitter account did not provide email");
user.setIsVerified(false); //TODO
if (email != null && !email.isEmpty()) {
user.setEmail(email);
}
}
else {
user.setEmail((String) values.get("email"));
user.setIsVerified(true); //TODO
}
user.setAvatarUrl(profile.getProfileImageUrl());
user.setId("" + profile.getId());
user.setName(profile.getName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.TWITTER);
user.setSecret(finalOauthToken.getValue());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
public OAuthToken getRequestToken() {
return this.twitterServiceProvider.getOAuthOperations().fetchRequestToken(this.environment.getProperty("twitter.login.redirect_uri"), null);
}
}

View File

@ -1,59 +0,0 @@
package eu.eudat.logic.security.validators.zenodo;
import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.security.customproviders.ORCID.ORCIDCustomProvider;
import eu.eudat.logic.security.customproviders.ORCID.ORCIDUser;
import eu.eudat.logic.security.customproviders.Zenodo.ZenodoAccessType;
import eu.eudat.logic.security.customproviders.Zenodo.ZenodoCustomProvider;
import eu.eudat.logic.security.customproviders.Zenodo.ZenodoUser;
import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoRequest;
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoResponseToken;
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.security.GeneralSecurityException;
@Component("zenodoTokenValidator")
public class ZenodoTokenValidator implements TokenValidator {
private ZenodoCustomProvider zenodoCustomProvider;
private Environment environment;
private AuthenticationService nonVerifiedUserAuthenticationService;
@Autowired
public ZenodoTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService, ZenodoCustomProvider zenodoCustomProvider) {
this.environment = environment;
this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService;
this.zenodoCustomProvider = zenodoCustomProvider;
}
@Override
public Principal validateToken(LoginInfo credentials) throws NonValidTokenException, IOException, GeneralSecurityException, NullEmailException {
ZenodoUser zenodoUser = new ZenodoUser().getZenodoUser(credentials.getData());
LoginProviderUser user = new LoginProviderUser();
user.setId(zenodoUser.getUserId());
user.setName(zenodoUser.getEmail());
user.setEmail(zenodoUser.getEmail());
user.setZenodoId(zenodoUser.getAccessToken());
user.setZenodoExpire(zenodoUser.getExpiresIn());
user.setZenodoRefresh(zenodoUser.getRefreshToken());
user.setProvider(credentials.getProvider());
user.setSecret(credentials.getTicket());
return this.nonVerifiedUserAuthenticationService.Touch(user);
}
public ZenodoResponseToken getAccessToken(ZenodoRequest zenodoRequest) {
return this.zenodoCustomProvider.getAccessToken(ZenodoAccessType.AUTHORIZATION_CODE, zenodoRequest.getCode()
, this.environment.getProperty("zenodo.login.client_id")
, this.environment.getProperty("zenodo.login.client_secret")
, this.environment.getProperty("zenodo.login.redirect_uri"));
}
}

View File

@ -2,7 +2,6 @@ package eu.eudat.logic.services.operations;
import eu.eudat.data.dao.entities.*;
import eu.eudat.data.dao.entities.security.CredentialDao;
import eu.eudat.data.dao.entities.security.UserTokenDao;
public interface DatabaseRepository {
@ -34,8 +33,6 @@ public interface DatabaseRepository {
CredentialDao getCredentialDao();
UserTokenDao getUserTokenDao();
ExternalDatasetDao getExternalDatasetDao();
UserDatasetProfileDao getUserDatasetProfileDao();

View File

@ -2,7 +2,6 @@ package eu.eudat.logic.services.operations;
import eu.eudat.data.dao.entities.*;
import eu.eudat.data.dao.entities.security.CredentialDao;
import eu.eudat.data.dao.entities.security.UserTokenDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -25,7 +24,6 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
private UserInfoDao userInfoDao;
private InvitationDao invitationDao;
private CredentialDao credentialDao;
private UserTokenDao userTokenDao;
private ExternalDatasetDao externalDatasetDao;
private UserRoleDao userRoleDao;
private UserDatasetProfileDao userDatasetProfileDao;
@ -174,16 +172,6 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
this.credentialDao = credentialDao;
}
@Override
public UserTokenDao getUserTokenDao() {
return userTokenDao;
}
@Autowired
public void setUserTokenDao(UserTokenDao userTokenDao) {
this.userTokenDao = userTokenDao;
}
@Override
public ExternalDatasetDao getExternalDatasetDao() {
return externalDatasetDao;

View File

@ -1,31 +1,16 @@
package eu.eudat.logic.services.operations.authentication;
import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.data.entities.UserToken;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.builders.entity.CredentialBuilder;
import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.logic.builders.entity.UserTokenBuilder;
import eu.eudat.logic.managers.MetricsManager;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.login.Credentials;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.Authorities;
import eu.eudat.types.MetricNames;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
public abstract class AbstractAuthenticationService implements AuthenticationService {
private static final Logger logger = LoggerFactory.getLogger(AbstractAuthenticationService.class);
@ -49,166 +34,13 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer
return dt;
}
abstract Principal Touch(UserToken token);
abstract Principal Touch(UserInfo token);
@Transactional
protected Credential autoCreateUser(String username, String password) {
if (!environment.getProperty("autouser.root.username").equals(username) || !environment.getProperty("autouser.root.password").equals(password))
return null;
UserInfo userInfo = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class)
.name(username).email(environment.getProperty("autouser.root.email")).created(new Date())
.lastloggedin(new Date()).authorization_level((short) 1).usertype((short) 1).userStatus((short)0)
.build();
userInfo = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().createOrUpdate(userInfo);
UserRole role = new UserRole();
role.setRole(Authorities.ADMIN.getValue());
role.setUserInfo(userInfo);
this.apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().createOrUpdate(role);
Credential credential = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(CredentialBuilder.class)
.id(UUID.randomUUID()).userInfo(userInfo).publicValue(username).secret(password)
.provider((int) TokenValidatorFactoryImpl.LoginProvider.NATIVELOGIN.getValue())
.creationTime(new Date()).lastUpdateTime(new Date()).status(0)
.build();
return this.apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao().createOrUpdate(credential);
}
public Principal Touch(UUID token) {
UserToken tokenEntry = this.apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().find(token);
if (tokenEntry == null || tokenEntry.getExpiresAt().before(new Date())) return null;
public Principal Touch(UUID userId) { //TODO: Authn
UserInfo tokenEntry = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userId);
if (tokenEntry == null) return null;
return this.Touch(tokenEntry);
}
public void Logout(UUID token) {
UserToken tokenEntry = this.apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().find(token);
this.apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().delete(tokenEntry);
}
public Principal Touch(Credentials credentials) throws NullEmailException {
Credential credential = this.apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao().getLoggedInCredentials(credentials.getUsername(), credentials.getSecret(), TokenValidatorFactoryImpl.LoginProvider.NATIVELOGIN.getValue());
if (credential == null && credentials.getUsername().equals(environment.getProperty("autouser.root.username"))) {
try {
credential = this.autoCreateUser(credentials.getUsername(), credentials.getSecret());
metricsManager.increaseValue(MetricNames.USERS, 1, MetricNames.TOTAL);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
if (credential == null) return null;
UserToken userToken = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserTokenBuilder.class)
.issuedAt(new Date()).user(credential.getUserInfo())
.token(UUID.randomUUID()).expiresAt(Timestamp.valueOf(LocalDateTime.now().plusDays(10)))
.build();
userToken = apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().createOrUpdate(userToken);
return this.Touch(userToken);
}
public Principal Touch(LoginProviderUser profile) throws NullEmailException {
UserInfo userInfo;// = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().withHint("userInfo").where((builder, root) -> builder.and(builder.equal(root.get("email"), profile.getEmail()), builder.equal(root.get("userStatus"), 0))).getSingleOrDefault();
//if (userInfo == null) {
Optional<Credential> optionalCredential = Optional.ofNullable(apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao()
.asQueryable().withHint("credentialUserInfo")
.where((builder, root) -> builder.and(builder.equal(root.get("provider"), profile.getProvider().getValue()), builder.equal(root.get("externalId"), profile.getId())))
.getSingleOrDefault());
userInfo = optionalCredential.map(Credential::getUserInfo).orElse(null);
if (userInfo != null) {
if (userInfo.getUserStatus() == 1) {
userInfo = null;
}
}
//}
if (userInfo == null) {
userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().withHint("userInfo").where((builder, root) -> builder.and(builder.equal(root.get("email"), profile.getEmail()), builder.equal(root.get("userStatus"), 0))).getSingleOrDefault();
}
final Credential credential = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(CredentialBuilder.class)
.id(UUID.randomUUID())
.creationTime(new Date())
.status(1)
.lastUpdateTime(new Date())
.provider(profile.getProvider().getValue())
.secret(profile.getSecret())
.externalId(profile.getId())
.email(profile.getEmail())
.build();
if (userInfo == null) {
userInfo = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class)
.name(profile.getName()).verified_email(profile.getIsVerified())
.email(profile.getEmail()).created(new Date()).lastloggedin(new Date())
.additionalinfo("{\"data\":{\"avatar\":{\"url\":\"" + profile.getAvatarUrl()
+ "\"},\"zenodoToken\":\"" + profile.getZenodoId()
+ "\", \"expirationDate\": \"" + Instant.now().plusSeconds((profile.getZenodoExpire() != null ? profile.getZenodoExpire(): 0)).toEpochMilli()
+ "\", \"zenodoRefresh\": \"" + profile.getZenodoRefresh()
+ (profile.getProvider() == TokenValidatorFactoryImpl.LoginProvider.ZENODO ? "\", \"zenodoEmail\": \"" + profile.getEmail() : "") +"\"}}")
.authorization_level((short) 1).usertype((short) 1).userStatus((short)0)
.build();
userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().createOrUpdate(userInfo);
credential.setPublicValue(userInfo.getName());
credential.setEmail(userInfo.getEmail());
credential.setUserInfo(userInfo);
apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao().createOrUpdate(credential);
UserRole role = new UserRole();
role.setRole(Authorities.USER.getValue());
role.setUserInfo(userInfo);
apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().createOrUpdate(role);
metricsManager.increaseValue(MetricNames.USERS, 1, MetricNames.TOTAL);
} else {
Map<String, Object> additionalInfo = userInfo.getAdditionalinfo() != null ?
new JSONObject(userInfo.getAdditionalinfo()).toMap() : new HashMap<>();
if (profile.getAvatarUrl() != null && !profile.getAvatarUrl().isEmpty() && !profile.getAvatarUrl().equals("null")) {
additionalInfo.put("avatarUrl", profile.getAvatarUrl());
}
if (profile.getZenodoId() != null && !profile.getZenodoId().isEmpty() && !profile.getZenodoId().equals("null")) {
additionalInfo.put("zenodoToken", profile.getZenodoId());
}
if (profile.getZenodoExpire() != null) {
additionalInfo.put("expirationDate", Instant.now().plusSeconds(profile.getZenodoExpire()).toEpochMilli());
}
if (profile.getZenodoRefresh() != null) {
additionalInfo.put("zenodoRefresh", profile.getZenodoRefresh());
}
if (profile.getProvider() == TokenValidatorFactoryImpl.LoginProvider.ZENODO) {
additionalInfo.put("zenodoEmail", profile.getEmail());
}
userInfo.setLastloggedin(new Date());
userInfo.setAdditionalinfo(new JSONObject(additionalInfo).toString());
Set<Credential> credentials = userInfo.getCredentials();
if (credentials.contains(credential)) {
Credential oldCredential = credentials.stream().filter(item -> credential.getProvider().equals(item.getProvider())).findFirst().get();
credential.setId(oldCredential.getId());
} else {
credential.setUserInfo(userInfo);
credential.setId(UUID.randomUUID());
credential.setPublicValue(userInfo.getName());
credential.setEmail(userInfo.getEmail());
apiContext.getOperationsContext().getDatabaseRepository().getCredentialDao().createOrUpdate(credential);
userInfo.getCredentials().add(credential);
}
userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().createOrUpdate(userInfo);
}
UserToken userToken = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserTokenBuilder.class)
.token(UUID.randomUUID()).user(userInfo)
.expiresAt(Timestamp.valueOf(LocalDateTime.now().plusDays(10))).issuedAt(new Date())
.build();
apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().createOrUpdate(userToken);
return Touch(userToken.getToken());
}
}

View File

@ -4,6 +4,7 @@ import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.models.data.login.Credentials;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import java.util.UUID;
@ -12,11 +13,7 @@ import java.util.UUID;
*/
public interface AuthenticationService {
Principal Touch(LoginProviderUser profile) throws NullEmailException;
Principal Touch(Credentials credentials) throws NullEmailException;
void Logout(UUID token);
Principal Touch(MyPrincipal principal) throws NullEmailException;
Principal Touch(UUID token) throws NullEmailException;
}

View File

@ -3,100 +3,65 @@ package eu.eudat.logic.services.operations.authentication;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.data.entities.UserToken;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.builders.model.models.PrincipalBuilder;
import eu.eudat.logic.managers.MetricsManager;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.Authorities;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
@Service("nonVerifiedUserAuthenticationService")
public class NonVerifiedUserEmailAuthenticationService extends AbstractAuthenticationService {
public NonVerifiedUserEmailAuthenticationService(ApiContext apiContext, Environment environment, MetricsManager metricsManager) {
private final ClaimExtractor claimExtractor;
public NonVerifiedUserEmailAuthenticationService(ApiContext apiContext, Environment environment, MetricsManager metricsManager, ClaimExtractor claimExtractor) {
super(apiContext, environment, metricsManager);
this.claimExtractor = claimExtractor;
}
public Principal Touch(UserToken token) {
if (token == null || token.getExpiresAt().before(new Date())) return null;
@Override
Principal Touch(UserInfo token) {
throw new NotImplementedException("");
}
UserInfo user = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(token.getUser().getId());
if (user == null) return null;
String avatarUrl;
try {
avatarUrl = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("avatarUrl").asText() : "";
} catch (Exception e) {
avatarUrl = "";
}
String zenodoToken;
try {
zenodoToken = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("zenodoToken").asText() : "";
} catch (Exception e) {
zenodoToken = "";
}
Instant zenodoDuration;
try {
zenodoDuration = user.getAdditionalinfo() != null ? Instant.ofEpochMilli(new ObjectMapper().readTree(user.getAdditionalinfo()).get("expirationDate").asLong()) : Instant.now();
} catch (Exception e) {
zenodoDuration = Instant.now();
}
String zenodoEmail;
try {
zenodoEmail = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("zenodoEmail").asText() : "";
} catch (Exception e) {
zenodoEmail = "";
}
String zenodoRefresh;
try {
zenodoRefresh = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("zenodoRefresh").asText() : "";
} catch (Exception e) {
zenodoRefresh = "";
}
String culture;
try {
culture = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("culture").get("name").asText() : "";
} catch (Exception e) {
culture = "";
}
String language;
try {
language = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("language").get("value").asText() : "";
} catch (Exception e) {
language = "";
}
String timezone;
try {
timezone = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("timezone").asText() : "";
} catch (Exception e) {
timezone = "";
}
Principal principal = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class)
.id(user.getId()).token(token.getToken())
.expiresAt(token.getExpiresAt())
.name(user.getName())
.email(user.getEmail())
.avatarUrl(avatarUrl)
.culture(culture)
.language(language)
.timezone(timezone)
.zenodoToken(zenodoToken)
.zenodoDuration(zenodoDuration)
.zenodoEmail(zenodoEmail)
.zenodoRefresh(zenodoRefresh)
@Override
public Principal Touch(MyPrincipal principal) throws NullEmailException { //TODO: Authn
if (principal == null /*|| this.claimExtractor.expiresAt(principal).isBefore(Instant.now())*/) return null;
Principal principalItem = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class)
.id(UUID.randomUUID()).token(UUID.randomUUID())//TODO: Authn
.expiresAt(Date.from(Instant.now().plus(5, ChronoUnit.DAYS)))
.name(this.claimExtractor.name(principal))
.email(this.claimExtractor.email(principal))
.avatarUrl("")
.culture("")
.language("")
.timezone("")
.zenodoToken("")
.zenodoDuration(Instant.now())
.zenodoEmail("")
.zenodoRefresh("")
.build();
principalItem.setAuthorities(new HashSet<>());
principalItem.getAuthz().add(Authorities.USER);
// List<UserRole> userRoles = apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().getUserRoles(user);
// for (UserRole item : userRoles) {
// if (principal.getAuthz() == null) principal.setAuthorities(new HashSet<>());
// principal.getAuthz().add(Authorities.fromInteger(item.getRole()));
// }
return principalItem;
List<UserRole> userRoles = apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().getUserRoles(user);
for (UserRole item : userRoles) {
if (principal.getAuthz() == null) principal.setAuthorities(new HashSet<>());
principal.getAuthz().add(Authorities.fromInteger(item.getRole()));
}
return principal;
}
}

View File

@ -1,28 +1,25 @@
package eu.eudat.logic.services.operations.authentication;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.data.entities.UserToken;
import eu.eudat.exceptions.security.NullEmailException;
import eu.eudat.logic.builders.entity.CredentialBuilder;
import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.logic.builders.entity.UserTokenBuilder;
import eu.eudat.logic.builders.model.models.PrincipalBuilder;
import eu.eudat.logic.managers.MetricsManager;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.login.Credentials;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.Authorities;
import org.json.JSONObject;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.*;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
@Service("verifiedUserAuthenticationService")
@ -32,10 +29,7 @@ public class VerifiedUserAuthenticationService extends AbstractAuthenticationSer
super(apiContext, environment, metricsManager);
}
public Principal Touch(UserToken token) {
if (token == null || token.getExpiresAt().before(new Date())) return null;
UserInfo user = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(token.getUser().getId());
public Principal Touch(UserInfo user) {
if (user == null) return null;
if (user.getEmail() == null) throw new NullEmailException();
String avatarUrl;
@ -87,8 +81,8 @@ public class VerifiedUserAuthenticationService extends AbstractAuthenticationSer
timezone = "";
}
Principal principal = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class)
.id(user.getId()).token(token.getToken())
.expiresAt(token.getExpiresAt())
.id(user.getId()).token(UUID.randomUUID()) //TODO: Authn
.expiresAt(Date.from(Instant.now().plus(5, ChronoUnit.DAYS)))//TODO: Authn
.name(user.getName())
.email(user.getEmail())
.avatarUrl(avatarUrl)
@ -108,4 +102,10 @@ public class VerifiedUserAuthenticationService extends AbstractAuthenticationSer
}
return principal;
}
@Override
public Principal Touch(MyPrincipal principal) throws NullEmailException {
throw new NotImplementedException("");
}
}

View File

@ -1,11 +1,8 @@
package eu.eudat.models.data.login;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
public class LoginInfo {
private String ticket;
private TokenValidatorFactoryImpl.LoginProvider provider;
private Object data;
public String getTicket() {
@ -16,13 +13,6 @@ public class LoginInfo {
this.ticket = ticket;
}
public TokenValidatorFactoryImpl.LoginProvider getProvider() {
return provider;
}
public void setProvider(Integer provider) {
this.provider = TokenValidatorFactoryImpl.LoginProvider.fromInteger(provider);
}
public Object getData() {
return data;

View File

@ -1,7 +1,5 @@
package eu.eudat.models.data.loginprovider;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
public class LoginProviderUser {
private String name;
@ -10,7 +8,6 @@ public class LoginProviderUser {
private String secret;
private String avatarUrl;
private boolean isVerified;
private TokenValidatorFactoryImpl.LoginProvider provider;
private String zenodoId;
private Integer zenodoExpire;
private String zenodoRefresh;
@ -47,14 +44,6 @@ public class LoginProviderUser {
isVerified = verified;
}
public TokenValidatorFactoryImpl.LoginProvider getProvider() {
return provider;
}
public void setProvider(TokenValidatorFactoryImpl.LoginProvider provider) {
this.provider = provider;
}
public String getSecret() {
return secret;
}

View File

@ -0,0 +1,165 @@
package eu.eudat.models.v2;
import gr.cite.tools.logging.annotation.LogSensitive;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class Account {
public static class PrincipalInfo {
public final static String _userId = "userId";
public UUID userId;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public final static String _subject = "subject";
public UUID subject;
public UUID getSubject() {
return subject;
}
public void setSubject(UUID subject) {
this.subject = subject;
}
public final static String _name = "name";
@LogSensitive
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public final static String _scope = "scope";
public List<String> scope;
public List<String> getScope() {
return scope;
}
public void setScope(List<String> scope) {
this.scope = scope;
}
public final static String _client = "client";
public String client;
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public final static String _notBefore = "notBefore";
public Instant notBefore;
public Instant getNotBefore() {
return notBefore;
}
public void setNotBefore(Instant notBefore) {
this.notBefore = notBefore;
}
public final static String _issuedAt = "issuedAt";
public Instant issuedAt;
public Instant getIssuedAt() {
return issuedAt;
}
public void setIssuedAt(Instant issuedAt) {
this.issuedAt = issuedAt;
}
public final static String _authenticatedAt = "authenticatedAt";
public Instant authenticatedAt;
public Instant getAuthenticatedAt() {
return authenticatedAt;
}
public void setAuthenticatedAt(Instant authenticatedAt) {
this.authenticatedAt = authenticatedAt;
}
public final static String _expiresAt = "expiresAt";
public Instant expiresAt;
public Instant getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(Instant expiresAt) {
this.expiresAt = expiresAt;
}
public final static String _more = "more";
@LogSensitive
public Map<String, List<String>> more;
public Map<String, List<String>> getMore() {
return more;
}
public void setMore(Map<String, List<String>> more) {
this.more = more;
}
}
public final static String _isAuthenticated = "isAuthenticated";
private Boolean isAuthenticated;
public Boolean getIsAuthenticated() {
return isAuthenticated;
}
public void setIsAuthenticated(Boolean authenticated) {
isAuthenticated = authenticated;
}
public final static String _principal = "principal";
private PrincipalInfo principal;
public PrincipalInfo getPrincipal() {
return principal;
}
public void setPrincipal(PrincipalInfo principal) {
this.principal = principal;
}
public final static String _roles = "roles";
private List<Integer> roles;
public Boolean getAuthenticated() {
return isAuthenticated;
}
public List<Integer> getRoles() {
return roles;
}
public void setRoles(List<Integer> roles) {
this.roles = roles;
}
}

View File

@ -0,0 +1,98 @@
package eu.eudat.models.v2;
import eu.eudat.commons.scope.UserScope;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.types.Authorities;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorKeys;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AccountBuilder {
private final ClaimExtractor claimExtractor;
private final Set<String> excludeMoreClaim;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final ApiContext apiContext;
private final UserScope userScope;
public AccountBuilder(ClaimExtractor claimExtractor, CurrentPrincipalResolver currentPrincipalResolver, ApiContext apiContext, UserScope userScope) {
this.claimExtractor = claimExtractor;
this.currentPrincipalResolver = currentPrincipalResolver;
this.apiContext = apiContext;
this.userScope = userScope;
this.excludeMoreClaim = Set.of(
ClaimExtractorKeys.Subject,
ClaimExtractorKeys.Name,
ClaimExtractorKeys.Scope,
ClaimExtractorKeys.Client,
ClaimExtractorKeys.IssuedAt,
ClaimExtractorKeys.NotBefore,
ClaimExtractorKeys.AuthenticatedAt,
ClaimExtractorKeys.ExpiresAt);
}
public Account build(FieldSet fields, MyPrincipal principal) {
Account model = new Account();
if (principal == null || !principal.isAuthenticated()) {
model.setIsAuthenticated(Boolean.FALSE);
return model;
}
model.setIsAuthenticated(Boolean.TRUE);
FieldSet principalFields = fields.extractPrefixed(BaseFieldSet.asIndexerPrefix(Account._principal));
if (!principalFields.isEmpty()) model.setPrincipal(new Account.PrincipalInfo());
if (principalFields.hasField(Account.PrincipalInfo._subject))
model.getPrincipal().setSubject(this.claimExtractor.subjectUUID(principal));
if (principalFields.hasField(Account.PrincipalInfo._userId))
model.getPrincipal().setUserId(this.userScope.getUserIdSafe());
if (principalFields.hasField(Account.PrincipalInfo._name))
model.getPrincipal().setName(this.claimExtractor.name(principal));
if (principalFields.hasField(Account.PrincipalInfo._scope))
model.getPrincipal().setScope(this.claimExtractor.scope(principal));
if (principalFields.hasField(Account.PrincipalInfo._client))
model.getPrincipal().setClient(this.claimExtractor.client(principal));
if (principalFields.hasField(Account.PrincipalInfo._issuedAt))
model.getPrincipal().setIssuedAt(this.claimExtractor.issuedAt(principal));
if (principalFields.hasField(Account.PrincipalInfo._notBefore))
model.getPrincipal().setNotBefore(this.claimExtractor.notBefore(principal));
if (principalFields.hasField(Account.PrincipalInfo._authenticatedAt))
model.getPrincipal().setAuthenticatedAt(this.claimExtractor.authenticatedAt(principal));
if (principalFields.hasField(Account.PrincipalInfo._expiresAt))
model.getPrincipal().setExpiresAt(this.claimExtractor.expiresAt(principal));
if (principalFields.hasField(Account.PrincipalInfo._more)) {
model.getPrincipal().setMore(new HashMap<>());
for (String key : this.claimExtractor.knownPublicKeys()) {
if (this.excludeMoreClaim.contains(key))
continue;
List<String> values = this.claimExtractor.asStrings(principal, key);
if (values == null || values.isEmpty())
continue;
if (!model.getPrincipal().getMore().containsKey(key))
model.getPrincipal().getMore().put(key, new ArrayList<>());
model.getPrincipal().getMore().get(key).addAll(values);
}
}
UserInfo user = this.userScope.isSet() ? this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(this.userScope.getUserIdSafe()) : null; //TODO: Authn
List<UserRole> userRoles = this.userScope.isSet() ?apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().getUserRoles(user) : new ArrayList<>();
if (fields.hasField(Account._roles)) {
//List<String> roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
//model.setRoles(roles);
model.setRoles(new ArrayList<>());
for (UserRole item : userRoles) {
model.getRoles().add(item.getRole());
}
}
return model;
}
}

View File

@ -12,4 +12,5 @@ spring:
optional:classpath:config/email.yml[.yml], optional:classpath:config/email-${spring.profiles.active}.yml[.yml], optional:file:../config/email-${spring.profiles.active}.yml[.yml],
optional:classpath:config/elasticsearch.yml[.yml], optional:classpath:config/elasticsearch-${spring.profiles.active}.yml[.yml], optional:file:../config/elasticsearch-${spring.profiles.active}.yml[.yml],
optional:classpath:config/file-path.yml[.yml], optional:classpath:config/file-path-${spring.profiles.active}.yml[.yml], optional:file:../config/file-path-${spring.profiles.active}.yml[.yml],
optional:classpath:config/idpclaims.yml[.yml], optional:classpath:config/idpclaims-${spring.profiles.active}.yml[.yml], optional:file:../config/idpclaims-${spring.profiles.active}.yml[.yml],
optional:classpath:config/external.yml[.yml], optional:classpath:config/external-${spring.profiles.active}.yml[.yml], optional:file:../config/external-${spring.profiles.active}.yml[.yml]

View File

@ -15,9 +15,9 @@ cache:
initialCapacity: 100
maximumSize: 500
enableRecordStats: false
expireAfterWriteMinutes: 1
expireAfterAccessMinutes: 1
refreshAfterWriteMinutes: 1
expireAfterWriteMinutes: 10
expireAfterAccessMinutes: 10
refreshAfterWriteMinutes: 10
- names: [ "supportiveMaterial" ]
allowNullValues: true
initialCapacity: 100

View File

@ -0,0 +1,39 @@
idpclient:
claims:
mapping:
Subject:
- type: sub
Name:
- type: name
Client:
- type: client_id
AuthenticationMethod:
- type: amr
NotBefore:
- type: nbf
AuthenticatedAt:
- type: auth_time
ExpiresAt:
- type: exp
Email:
- type: email
Roles:
- type: resource_access
path: dmp_web.roles
Scope:
- type: scope
AccessToken:
- type: x-access-token
visibility: SENSITIVE
IssuedAt:
- type: iat
Issuer:
- type: iss
Audience:
- type: aud
TokenType:
- type: typ
AuthorizedParty:
- type: azp
Authorities:
- type: authorities

View File

@ -1,3 +1,22 @@
web:
security:
enabled: true
authorized-endpoints: [ api ]
allowed-endpoints: [ api/public ]
idp:
api-key:
enabled: true
authorization-header: Authorization
client-id: ${IDP_APIKEY_CLIENT_ID:}
client-secret: ${IDP_APIKEY_CLIENT_SECRET:}
scope: ${IDP_APIKEY_SCOPE:}
resource:
opaque:
client-id: ${IDP_OPAQUE_CLIENT_ID:}
client-secret: ${IDP_OPAQUE_CLIENT_SECRET:}
jwt:
claims: [ role, x-role ]
autouser:
root:
email: ${AUTOUSER_EMAIL:}

View File

@ -149,5 +149,8 @@
"@schematics/angular:directive": {
"prefix": "app"
}
},
"cli": {
"analytics": false
}
}

View File

@ -31,6 +31,8 @@
"dragula": "^3.7.3",
"file-saver": "^2.0.5",
"moment": "^2.29.4",
"keycloak-angular": "^14.0.0",
"keycloak-js": "^20.0.5",
"moment-timezone": "^0.5.43",
"ng-dialog-animation": "^9.0.4",
"ng2-dragula": "^5.0.1",

View File

@ -254,6 +254,7 @@ const appRoutes: Routes = [
title: 'GENERAL.TITLES.LOGIN'
},
},
{ path: 'logout', loadChildren: () => import('./ui/auth/logout/logout.module').then(m => m.LogoutModule) },
{
path: 'api/oauth/authorized/b2access',
component: B2AccessLoginComponent,

View File

@ -210,7 +210,7 @@ export class AppComponent implements OnInit, AfterViewInit {
}
public isAuthenticated(): boolean {
return !(!this.authentication.current());
return this.authentication.currentAccountIsAuthenticated();
}
goToDMPs() {
@ -224,8 +224,8 @@ export class AppComponent implements OnInit, AfterViewInit {
initializeServices() {
this.translate.setDefaultLang(this.configurationService.defaultLanguage || 'en');
this.authentication.current() && this.authentication.current().culture ? this.cultureService.cultureSelected(this.authentication.current().culture) : this.cultureService.cultureSelected(this.configurationService.defaultCulture);
this.authentication.current() && this.authentication.current().language ? this.language.changeLanguage(this.authentication.current().language) : (this.configurationService.defaultLanguage || 'en');
this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileCulture() ? this.cultureService.cultureSelected(this.authentication.getUserProfileCulture()) : this.cultureService.cultureSelected(this.configurationService.defaultCulture);
this.authentication.currentAccountIsAuthenticated() && this.authentication.getUserProfileLanguage() ? this.language.changeLanguage(this.authentication.getUserProfileLanguage()) : (this.configurationService.defaultLanguage || 'en');
}
toggleNavbar(event) {

View File

@ -1,6 +1,6 @@
import { OverlayModule } from '@angular/cdk/overlay';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { LOCALE_ID, NgModule } from '@angular/core';
import { APP_INITIALIZER, LOCALE_ID, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MAT_MOMENT_DATE_FORMATS, MatMomentDateModule } from '@angular/material-moment-adapter';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
@ -34,6 +34,11 @@ import { MatomoService } from './core/services/matomo/matomo-service';
import { GuidedTourModule } from './library/guided-tour/guided-tour.module';
import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module';
import { OpenDMPCustomTranslationCompiler } from './utilities/translate/opendmp-custom-translation-compiler';
import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
import { BaseHttpParams } from '@common/http/base-http-params';
import { InterceptorType } from '@common/http/interceptors/interceptor-type';
import { from } from 'rxjs';
import { AuthService } from './core/services/auth/auth.service';
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient, appConfig: ConfigurationService) {
@ -77,10 +82,42 @@ const appearance: MatFormFieldDefaultOptions = {
// appearance: 'standard'
};
export function InstallationConfigurationFactory(appConfig: ConfigurationService, keycloak: KeycloakService, authService: AuthService) {
return () => appConfig.loadConfiguration().then(x => keycloak.init({
config: {
url: appConfig.keycloak.address,
realm: appConfig.keycloak.realm,
clientId: appConfig.keycloak.clientId,
},
initOptions: {
onLoad: 'check-sso',
flow: appConfig.keycloak.flow,
checkLoginIframe: false,
scope: appConfig.keycloak.scope,
pkceMethod: 'S256'
},
shouldAddToken: () => false
}).then(() => {
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [
InterceptorType.Locale,
InterceptorType.ProgressIndication,
InterceptorType.RequestTiming,
InterceptorType.UnauthorizedResponse,
]
};
const tokenPromise = keycloak.getToken();
return authService.prepareAuthRequest(from(tokenPromise), {params}).toPromise().catch(error => authService.onAuthenticateError(error));
}));
}
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
KeycloakAngularModule,
CoreServiceModule.forRoot(),
AppRoutingModule,
CommonUiModule,
@ -120,6 +157,13 @@ const appearance: MatFormFieldDefaultOptions = {
ReloadHelperComponent
],
providers: [
ConfigurationService,
{
provide: APP_INITIALIZER,
useFactory: InstallationConfigurationFactory,
deps: [ConfigurationService, KeycloakService, AuthService],
multi: true
},
{
provide: MAT_DATE_LOCALE,
deps: [CultureService],

View File

@ -9,14 +9,8 @@ export class AdminAuthGuard implements CanActivate, CanLoad {
}
isAdmin(): boolean {
if (!this.auth.current()) { return false; }
const principalRoles = this.auth.current().authorities;
for (let i = 0; i < principalRoles.length; i++) {
if (principalRoles[i] === AppRole.Admin) {
return true;
}
}
return false;
if (!this.auth.currentAccountIsAuthenticated()) { return false; }
return this.auth.hasRole(AppRole.Admin);
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

View File

@ -1,27 +1,40 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router';
import { AuthService } from './services/auth/auth.service';
import { from, Observable, of as observableOf } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate, CanLoad {
constructor(private auth: AuthService, private router: Router) {
constructor(private authService: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
const url: string = state.url;
if (!this.auth.current()) {
this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } });
return false;
}
return true;
return this.applyGuard(url);
}
canLoad(route: Route): boolean {
canLoad(route: Route): Observable<boolean> {
const url = `/${route.path}`;
if (!this.auth.current()) {
this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } });
return false;
return this.applyGuard(url);
}
private applyGuard(url: string) {
return this.checkLogin(url).pipe(tap(loggedIn => {
if (!loggedIn) {
this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } });
} else{
return true;
}
}));
}
private checkLogin(url: string): Observable<boolean> {
if (!this.authService.isLoggedIn()) { return observableOf(false); }
return this.authService.hasAccessToken()
? observableOf(true)
: from(this.authService.refreshToken()).pipe(
catchError(x => observableOf(false)));
}
}

View File

@ -54,16 +54,17 @@ import { TermsOfServiceService } from './services/terms-of-service/terms-of-serv
import { UnlinkAccountEmailConfirmationService } from './services/unlink-account-email-confirmation/unlink-account-email-confirmation.service';
import { DescriptionTemplateTypeService } from './services/description-template-type/description-template-type.service';
import { BaseHttpV2Service } from './services/http/base-http-v2.service';
import { KeycloakService } from 'keycloak-angular';
import { PrincipalService } from './services/http/principal.service';
import { InterceptorType } from '@common/http/interceptors/interceptor-type';
import { BaseHttpParams } from '@common/http/base-http-params';
import { from } from 'rxjs';
//
//
// This is shared module that provides all the services. Its imported only once on the AppModule.
//
//
export function ConfigurationFactory(appConfig: ConfigurationService) {
return () => appConfig.loadConfiguration();
}
@NgModule({
})
export class CoreServiceModule {
@ -121,19 +122,13 @@ export class CoreServiceModule {
LockService,
UserGuideService,
AboutService,
PrincipalService,
FaqService,
GlossaryService,
TermsOfServiceService,
CurrencyService,
MergeEmailConfirmationService,
UnlinkAccountEmailConfirmationService,
ConfigurationService,
{
provide: APP_INITIALIZER,
useFactory: ConfigurationFactory,
deps: [ConfigurationService, HttpClient],
multi: true
},
LanguageInfoService,
PrefillingService,
DescriptionTemplateTypeService

View File

@ -1,15 +1,28 @@
import { AppRole } from "../../common/enum/app-role";
import { AppRole } from "@app/core/common/enum/app-role";
import { Guid } from "@common/types/guid";
export interface Principal {
id: string;
token: string;
name: string;
email: string;
expiresAt: Date;
authorities: AppRole[];
avatarUrl: string;
timezone: string;
language: string;
culture: string;
zenodoEmail: string;
export interface AppAccount {
isAuthenticated: boolean;
// permissions: AppPermission[];
roles: AppRole[];
principal: AppPrincipalInfo;
profile: UserProfileInfo;
}
export interface AppPrincipalInfo{
subject: Guid;
name: string;
scope: string[];
client: string;
notBefore: Date;
authenticatedAt: Date;
expiresAt: Date;
more: Record<string, string[]>
}
export interface UserProfileInfo {
culture: string;
language: string;
timezone: string;
avatarUrl: string;
email: string;
}

View File

@ -0,0 +1,54 @@
import { KeycloakFlow } from 'keycloak-js';
import { LoginConfiguration } from './login-configuration.model';
export class KeycloakConfiguration {
private _enabled: boolean
get enabled(): boolean {
return this._enabled;
}
private _address: string
get address(): string {
return this._address;
}
private _realm: string
get realm(): string {
return this._realm;
}
private _flow: KeycloakFlow
get flow(): KeycloakFlow {
return this._flow;
}
private _clientId: string
get clientId(): string {
return this._clientId;
}
private _silentCheckSsoRedirectUri: string
get silentCheckSsoRedirectUri(): string {
return this._silentCheckSsoRedirectUri;
}
private _scope: string
get scope(): string {
return this._scope;
}
public static parseValue(value: any): KeycloakConfiguration {
const obj: KeycloakConfiguration = new KeycloakConfiguration();
obj._enabled = value.enabled;
obj._address = value.address;
obj._realm = value.realm;
obj._flow = value.flow;
obj._clientId = value.clientId;
obj._silentCheckSsoRedirectUri = value.silentCheckSsoRedirectUri;
obj._scope = value.scope;
return obj;
}
}

View File

@ -1,203 +1,312 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { Credential } from '@app/core/model/auth/credential';
import { LoginInfo } from '@app/core/model/auth/login-info';
import { Principal } from '@app/core/model/auth/principal';
import { AppAccount } from '@app/core/model/auth/principal';
import { ConfigurableProvider } from '@app/core/model/configurable-provider/configurableProvider';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { BaseService } from '@common/base/base.service';
import { TranslateService } from '@ngx-translate/core';
import { environment } from 'environments/environment';
import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs';
import { catchError, map, takeUntil } from 'rxjs/operators';
import { Observable, Subject, forkJoin, from, of as observableOf, throwError as observableThrowError } from 'rxjs';
import { catchError, exhaustMap, map, takeUntil } from 'rxjs/operators';
import { ConfigurationService } from '../configuration/configuration.service';
import { CookieService } from 'ngx-cookie-service';
import { Guid } from '@common/types/guid';
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
import { NgZone } from '@angular/core';
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
import { PrincipalService } from '../http/principal.service';
import { AppRole } from '@app/core/common/enum/app-role';
export interface AuthenticationState {
loginStatus: LoginStatus;
}
export enum LoginStatus {
LoggedIn = 0,
LoggingOut = 1,
LoggedOut = 2
}
@Injectable()
export class AuthService extends BaseService {
private actionUrl: string;
private headers: HttpHeaders;
public authenticationStateSubject: Subject<AuthenticationState>;
private accessToken: string;
private appAccount: AppAccount;
private _authState: boolean;
constructor(
private http: HttpClient,
private snackBar: MatSnackBar,
private installationConfiguration: ConfigurationService,
private language: TranslateService,
private router: Router,
private zone: NgZone,
private keycloakService: KeycloakService,
private uiNotificationService: UiNotificationService,
private configurationService: ConfigurationService,
private cookieService: CookieService
private principalService: PrincipalService
) {
super();
this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
this.authenticationStateSubject = new Subject<AuthenticationState>();
window.addEventListener('storage', (event: StorageEvent) => {
// Logout if we receive event that logout action occurred in a different tab.
if (
event.key &&
event.key === 'authState' &&
event.newValue === 'false' &&
this._authState
) {
this.clear();
this.router.navigate(['/unauthorized'], {
queryParams: { returnUrl: this.router.url },
});
}
});
}
public getAuthenticationStateObservable(): Observable<AuthenticationState> {
return this.authenticationStateSubject.asObservable();
}
public beginLogOutProcess(): void {
this.authenticationStateSubject.next({
loginStatus: LoginStatus.LoggingOut,
});
}
public clear(): void {
localStorage.removeItem('principal');
this.authState(false);
this.accessToken = undefined;
this.appAccount = undefined;
}
public current(principal?: Principal): Principal {
if (principal) {
localStorage.setItem('principal', JSON.stringify(principal));
return principal;
private authState(authState?: boolean): boolean {
if (authState !== undefined) {
this._authState = authState;
localStorage.setItem('authState', authState ? 'true' : 'false');
if (authState) {
this.authenticationStateSubject.next({
loginStatus: LoginStatus.LoggedIn,
});
} else {
this.authenticationStateSubject.next({
loginStatus: LoginStatus.LoggedOut,
});
}
}
if (this._authState === undefined) {
this._authState =
localStorage.getItem('authState') === 'true' ? true : false;
}
return this._authState;
}
public currentAccountIsAuthenticated(): boolean {
return this.appAccount && this.appAccount.isAuthenticated;
}
//Should this be name @isAuthenticated@ instead?
public hasAccessToken(): boolean {
return Boolean(this.currentAuthenticationToken());
}
public currentAuthenticationToken(accessToken?: string): string {
if (accessToken) {
this.accessToken = accessToken;
}
return this.accessToken;
}
public userId(): Guid {
if (
this.appAccount &&
this.appAccount.principal &&
this.appAccount.principal.subject
) {
return this.appAccount.principal.subject;
}
const principalJson = localStorage.getItem('principal');
if (principalJson === null || principalJson === undefined) {
return null;
}
let principalObj = JSON.parse(principalJson) as Principal;
principalObj.expiresAt = new Date(principalObj.expiresAt);
if (principalObj.expiresAt < new Date()) {
return null;
public isLoggedIn(): boolean {
return this.authState();
}
return principalObj;
}
//public login(credential: Credential): Observable<Principal> {
// const url = this.actionUrl + 'login';
// return this.http.post(url, credential, { headers: this.headers })
// .map((res: Response) => {
// let principal = this.current(new JsonSerializer<Principal>().fromJSONObject(res, Principal));
// //this.loginContextSubject.next(true);
// return principal;
// })
// .catch((error: any) => {
// //this.loginContextSubject.next(false);
// return Observable.throw(error);
// });
//}
public login(loginInfo: LoginInfo): Observable<Principal> {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'externallogin';
return this.http.post(url, loginInfo, { headers: this.headers }).pipe(
map((res: any) => {
const principal = this.current(res.payload);
// this.cookieService.set('cookiesConsent', 'true', 356);
this.cookieService.set("cookiesConsent", "true", 356,null,null,false, 'Lax');
//this.loginContextSubject.next(true);
return principal;
}),
catchError((error: any) => {
//this.loginContextSubject.next(false);
return observableThrowError(error);
}));
}
public mergeLogin(loginInfo: LoginInfo): Observable<any> {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'externallogin';
return this.http.post(url, loginInfo, { headers: this.headers });
}
public nativeLogin(credentials: Credential): Observable<Principal> {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'nativelogin';
return this.http.post(url, credentials, { headers: this.headers }).pipe(
map((res: any) => {
const principal = this.current(res.payload);
// this.cookieService.set('cookiesConsent', 'true', 356);
this.cookieService.set("cookiesConsent", "true", 356,null,null,false, 'Lax');
//this.loginContextSubject.next(true);
return principal;
}),
catchError((error: any) => {
//this.loginContextSubject.next(false);
return observableThrowError(error);
}));
}
public logout(): void {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'logout';
const principal = this.current();
this.clear();
if (!principal) { return; }
let headers = this.headers;
headers = headers.set('AuthToken', principal.token);
this.http.post(url, null, { headers: headers })
.pipe(takeUntil(this._destroyed))
.subscribe(
res => this.onLogOutSuccess(res),
error => this.onLogOutError(error)
public prepareAuthRequest(observable: Observable<string>, httpParams?: Object): Observable<boolean> {
return observable.pipe(
map((x) => this.currentAuthenticationToken(x)),
exhaustMap(() => forkJoin([
this.principalService.me(httpParams)
])),
map((item) => {
this.currentAccount(item[0]);
return true;
})
);
}
public me(): Observable<Principal> {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'me';
const principal = this.current();
if (!principal) {
this.clear();
return observableOf<Principal>();
}
let headers = this.headers;
headers = headers.set('AuthToken', principal.token);
return this.http.post(url, null, { headers: headers }).pipe(
map((res: any) => {
const princ = this.current(res.payload);
princ.expiresAt = new Date(princ.expiresAt);
console.log("Token Expires at: " + princ.expiresAt.toDateString() + ' ' + princ.expiresAt.toLocaleTimeString());
return princ;
}),
catchError((error: any) => {
//console.warn('could not retrieve me info:\n', error);
this.clear();
const princ = this.current();
this.router.navigate(['/login']);
return observableOf<Principal>(princ);
}));
}
public onLogOutSuccess(logoutMessage: any) {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGOUT'), SnackBarNotificationLevel.Success);
this.router.navigate(['/login']);
}
public onLogOutError(errorMessage: string) {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGOUT'), SnackBarNotificationLevel.Error);
this.router.navigate(['/login']);
}
public getConfigurableProviders(): Observable<ConfigurableProvider[]> {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'configurableLogin';
return this.http.get<ConfigurableProvider[]>(url, { headers: this.headers }).pipe(
map((res: any) => {
const providers = res.payload.providers;
return providers;
public refresh(): Observable<boolean> {
return this.principalService.me().pipe(
map((item) => {
this.currentAccount(item);
return true;
})
);
}
public getUserFromToken(token: string): Observable<Principal> {
this.actionUrl = this.configurationService.server + 'auth/';
const url = this.actionUrl + 'me';
let headers = this.headers;
headers = headers.set('AuthToken', token);
return this.http.post(url, null, { headers: headers }).pipe(
map((res: any) => {
const princ = this.current(res.payload);
princ.expiresAt = new Date(princ.expiresAt);
return princ;
}),
catchError((error: any) => {
this.clear();
const princ = this.current();
this.router.navigate(['/login']);
return observableOf<Principal>(princ);
}));
private currentAccount(
appAccount: AppAccount
): void {
this.appAccount = appAccount;
this.authState(true);
}
public getPrincipalName(): string {
if (this.appAccount && this.appAccount.principal) {
return this.appAccount.principal.name;
}
return null;
}
public getRoles(): AppRole[] {
if (this.appAccount && this.appAccount.roles) {
return this.appAccount.roles;
}
return null;
}
public getUserProfileEmail(): string {
if (this.appAccount && this.appAccount.profile) {
return this.appAccount.profile.email;
}
return null;
}
public getUserProfileLanguage(): string {
if (this.appAccount && this.appAccount.profile) {
return this.appAccount.profile.language;
}
return null;
}
public hasAnyRole(roles: AppRole[]): boolean {
if (!roles) {
return false;
}
return roles.filter((r) => this.hasRole(r)).length > 0;
}
public hasRole(role: AppRole): boolean {
if (role === undefined) {
return false;
}
if (
!this.appAccount ||
!this.appAccount.roles ||
this.appAccount.roles.length === 0
) {
return false;
}
return this.appAccount.roles
.includes(role);
}
public getUserProfileCulture(): string {
if (this.appAccount && this.appAccount.profile) {
return this.appAccount.profile.culture;
}
return null;
}
public getUserProfileAvatarUrl(): string {
if (this.appAccount && this.appAccount.profile) {
return this.appAccount.profile.avatarUrl;
}
return null;
}
public getUserProfileTimezone(): string {
if (this.appAccount && this.appAccount.profile) {
return this.appAccount.profile.timezone;
}
return null;
}
public authenticate(returnUrl: string) {
this.keycloakService.isLoggedIn().then((isLoggedIn) => {
if (!isLoggedIn) {
this.keycloakService.login({
scope: this.installationConfiguration.keycloak.scope,
})
.then(() => {
console.log('Keycloak Login');
this.keycloakService.keycloakEvents$.subscribe({
next: (e) => {
if (
e.type === KeycloakEventType.OnTokenExpired
) {
this.refreshToken({});
}
},
});
this.onAuthenticateSuccess(returnUrl);
})
.catch((error) => this.onAuthenticateError(error));
} else {
this.zone.run(() => this.router.navigate([returnUrl]));
}
});
}
public refreshToken(httpParams?: Object): Promise<boolean> {
return this.keycloakService.updateToken(60).then((isRefreshed) => {
if (!isRefreshed) {
return false;
}
return this.prepareAuthRequest(
from(this.keycloakService.getToken()),
httpParams
)
.pipe(takeUntil(this._destroyed))
.pipe(
map(
() => {
return true;
},
(error) => {
this.onAuthenticateError(error);
return false;
}
)
)
.toPromise();
});
}
onAuthenticateError(errorResponse: HttpErrorResponse) {
this.zone.run(() => {
// const error: HttpError =
// this.httpErrorHandlingService.getError(errorResponse);
this.uiNotificationService.snackBarNotification(
// error.getMessagesString(),
errorResponse.message,
SnackBarNotificationLevel.Warning
);
});
}
onAuthenticateSuccess(returnUrl: string): void {
this.authState(true);
this.uiNotificationService.snackBarNotification(
this.language.instant('COMMONS.SNACK-BAR.SUCCESSFUL-LOGIN'),
SnackBarNotificationLevel.Success
);
this.zone.run(() => this.router.navigate([returnUrl]));
}
}

View File

@ -8,6 +8,7 @@ import { HelpService } from '@app/core/model/configuration-models/help-service.m
import { LoginProviders } from '@app/core/model/configuration-models/login-providers.model';
import { Logging } from '@app/core/model/configuration-models/logging.model';
import { HttpClient } from '@angular/common/http';
import { KeycloakConfiguration } from '@app/core/model/configuration-models/keycloak-configuration.model';
@Injectable({
providedIn: 'root',
@ -101,31 +102,47 @@ export class ConfigurationService extends BaseComponent {
return this._maxFileSizeInMB;
}
private _keycloak: KeycloakConfiguration;
get keycloak(): KeycloakConfiguration {
return this._keycloak;
}
public loadConfiguration(): Promise<any> {
return new Promise((r, e) => {
// We need to exclude all interceptors here, for the initial configuration request.
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.AuthToken,
excludedInterceptors: [
InterceptorType.AuthToken,
InterceptorType.JSONContentType,
InterceptorType.Locale,
InterceptorType.ProgressIndication,
InterceptorType.RequestTiming,
InterceptorType.UnauthorizedResponse]
InterceptorType.UnauthorizedResponse,
],
};
this.http.get('./assets/config/config.json', { params: params }).pipe(catchError((err: any, caught: Observable<any>) => throwError(err)))
this.http
.get("./assets/config/config.json", { params: params })
.pipe(
catchError((err: any, caught: Observable<any>) =>
throwError(err)
)
)
.pipe(takeUntil(this._destroyed))
.subscribe(
(content: ConfigurationService) => {
this.parseResponse(content);
r(this);
},
reason => e(reason));
(reason) => e(reason)
);
});
}
private parseResponse(config: any) {
this._server = config.Server;
this._app = config.App;
@ -134,6 +151,7 @@ export class ConfigurationService extends BaseComponent {
this._defaultLanguage = config.defaultLanguage;
this._availableLanguages = config.availableLanguages;
this._loginProviders = LoginProviders.parseValue(config.loginProviders);
this._keycloak = KeycloakConfiguration.parseValue(config.keycloak);
this._logging = Logging.parseValue(config.logging);
this._lockInterval = config.lockInterval;
this._guideAssets = config.guideAssets;

View File

@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpService } from './base-http.service';
import { Observable } from 'rxjs';
import { AppAccount } from '@app/core/model/auth/principal';
@Injectable()
export class PrincipalService {
private get apiBase(): string { return `${this.installationConfiguration.server}principal`; }
constructor(
private installationConfiguration: ConfigurationService,
private http: BaseHttpService
) { }
public me(options?: Object): Observable<AppAccount> {
const url = `${this.apiBase}/me`;
return this.http.get<AppAccount>(url, options);
}
}

View File

@ -23,24 +23,24 @@ export class MatomoService {
trackPageView(customTitle?: string): void {
if (this.configurationService.matomoEnabled) {
var principal = this.authService.current();
if (principal != null) { this.matomoTracker.setUserId(principal.id); }
var principalid = this.authService.userId();
if (principalid != null) { this.matomoTracker.setUserId(principalid.toString()); }
this.matomoTracker.trackPageView(customTitle);
}
}
trackSiteSearch(keyword: string, category?: string, resultsCount?: number): void {
if (this.configurationService.matomoEnabled) {
var principal = this.authService.current();
if (principal != null) { this.matomoTracker.setUserId(principal.id); }
var principalid = this.authService.userId();
if (principalid != null) { this.matomoTracker.setUserId(principalid.toString()); }
this.matomoTracker.trackSiteSearch(keyword, category, resultsCount);
}
}
trackDownload(category: "dmps" | "datasets", type: "docx" | "pdf" | "xml" | "json", id: string): void {
if (this.configurationService.matomoEnabled) {
var principal = this.authService.current();
if (principal != null) { this.matomoTracker.setUserId(principal.id); }
var principalid = this.authService.userId();
if (principalid != null) { this.matomoTracker.setUserId(principalid.toString()); }
this.matomoTracker.trackLink(this.configurationService.server + category + "/" + type + "/" + id, "download");
// this.matomoTracker.trackLink(url, "download");

View File

@ -9,14 +9,8 @@ export class SpecialAuthGuard implements CanActivate, CanLoad {
}
hasPermission(permission: AppRole): boolean {
if (!this.auth.current()) { return false; }
const principalRoles = this.auth.current().authorities;
for (let i = 0; i < principalRoles.length; i++) {
if (principalRoles[i] === permission) {
return true;
}
}
return false;
if (!this.auth.currentAccountIsAuthenticated()) { return false; }
return this.auth.hasRole(permission);
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {

View File

@ -177,12 +177,4 @@ export class UserListingComponent extends BaseComponent implements OnInit, After
public setDefaultAvatar(ev: Event) {
(ev.target as HTMLImageElement).src = 'assets/images/profile-placeholder.png';
}
// public principalHasAvatar(): boolean {
// return this.authentication.current().avatarUrl != null && this.authentication.current().avatarUrl.length > 0;
// }
// public getPrincipalAvatar(): string {
// return this.authentication.current().avatarUrl;
// }
}

View File

@ -42,18 +42,18 @@ export class AdminLoginComponent extends BaseComponent implements OnInit {
}
public nativeLogin() {
this.authService.nativeLogin(this.credential)
.pipe(takeUntil(this._destroyed))
.subscribe(
res => this.onLogInSuccess(res),
error => this.onLogInError(error)
);
// this.authService.nativeLogin(this.credential)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// res => this.onLogInSuccess(res),
// error => this.onLogInError(error)
// );
}
public onLogInSuccess(loginResponse: any) {
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success);
if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); }
if (this.authService.current().language) { this.language.changeLanguage(this.authService.current().language); }
if (this.authService.currentAccountIsAuthenticated() && this.authService.getUserProfileCulture()) { this.cultureService.cultureSelected(this.authService.getUserProfileCulture()); }
if (this.authService.currentAccountIsAuthenticated() && this.authService.getUserProfileLanguage()) { this.language.changeLanguage(this.authService.getUserProfileLanguage()); }
this.router.navigate(['/']);
}

View File

@ -48,18 +48,18 @@ export class B2AccessLoginComponent extends BaseComponent implements OnInit {
}
public b2AccessLogin(code: String) {
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json');
headers = headers.set('Accept', 'application/json');
this.httpClient.post(this.configurationService.server + 'auth/b2AccessRequestToken', { code: code }, { headers: headers })
.pipe(takeUntil(this._destroyed))
.subscribe((data: any) => {
this.authService.login({ ticket: data.payload.accessToken, provider: AuthProvider.B2Access, data: null })
.pipe(takeUntil(this._destroyed))
.subscribe(
res => this.loginService.onLogInSuccess(res, this.returnUrl),
error => this.loginService.onLogInError(error)
);
});
// let headers = new HttpHeaders();
// headers = headers.set('Content-Type', 'application/json');
// headers = headers.set('Accept', 'application/json');
// this.httpClient.post(this.configurationService.server + 'auth/b2AccessRequestToken', { code: code }, { headers: headers })
// .pipe(takeUntil(this._destroyed))
// .subscribe((data: any) => {
// this.authService.login({ ticket: data.payload.accessToken, provider: AuthProvider.B2Access, data: null })
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// res => this.loginService.onLogInSuccess(res, this.returnUrl),
// error => this.loginService.onLogInError(error)
// );
// });
}
}

Some files were not shown because too many files have changed in this diff Show More