From 23116d9a99c8289f8e9a7be34e671fee762ea9ad Mon Sep 17 00:00:00 2001 From: gkolokythas Date: Fri, 12 Jul 2019 17:22:57 +0300 Subject: [PATCH] Adds OrcId login. (Issue #103) --- .../main/java/eu/eudat/controllers/Login.java | 6 ++ .../B2AccessCustomProvider.java | 2 +- .../B2AccessCustomProviderImpl.java | 2 +- .../{ => B2Access}/B2AccessUser.java | 2 +- .../ORCID/ORCIDCustomProvider.java | 9 ++ .../ORCID/ORCIDCustomProviderImpl.java | 65 ++++++++++++++ .../customproviders/ORCID/ORCIDUser.java | 38 ++++++++ .../validators/orcid/ORCIDTokenValidator.java | 54 ++++++++++++ .../orcid/helpers/ORCIDRequest.java | 12 +++ .../orcid/helpers/ORCIDResponseToken.java | 28 ++++++ .../src/app/core/common/enum/auth-provider.ts | 3 +- .../src/app/core/model/orcid/orcidUser.ts | 5 ++ .../app/ui/auth/login/img/ORCIDiD_medium.png | Bin 0 -> 1542 bytes .../app/ui/auth/login/login.component.html | 43 ++++++---- .../app/ui/auth/login/login.component.scss | 14 +++ .../src/app/ui/auth/login/login.component.ts | 11 ++- .../src/app/ui/auth/login/login.module.ts | 6 +- .../src/app/ui/auth/login/login.routing.ts | 9 +- .../orcid-login/orcid-login.component.html | 0 .../orcid-login/orcid-login.component.scss | 0 .../orcid-login/orcid-login.component.ts | 81 ++++++++++++++++++ .../src/environments/environment.prod.ts | 7 +- .../src/environments/environment.staging.ts | 7 +- dmp-frontend/src/environments/environment.ts | 7 +- 24 files changed, 383 insertions(+), 28 deletions(-) rename dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/{ => B2Access}/B2AccessCustomProvider.java (85%) rename dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/{ => B2Access}/B2AccessCustomProviderImpl.java (98%) rename dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/{ => B2Access}/B2AccessUser.java (90%) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProvider.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProviderImpl.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDUser.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/ORCIDTokenValidator.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDRequest.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDResponseToken.java create mode 100644 dmp-frontend/src/app/core/model/orcid/orcidUser.ts create mode 100644 dmp-frontend/src/app/ui/auth/login/img/ORCIDiD_medium.png create mode 100644 dmp-frontend/src/app/ui/auth/login/orcid-login/orcid-login.component.html create mode 100644 dmp-frontend/src/app/ui/auth/login/orcid-login/orcid-login.component.scss create mode 100644 dmp-frontend/src/app/ui/auth/login/orcid-login/orcid-login.component.ts diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java index 29cf87104..a6315f15a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java @@ -82,6 +82,12 @@ public class Login { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(this.b2AccessTokenValidator.getAccessToken(b2AccessRequest)).status(ApiMessageCode.NO_MESSAGE)); } + @RequestMapping(method = RequestMethod.POST, value = {"/orcidRequestToken"}, produces = "application/json", consumes = "application/json") + public @ResponseBody + ResponseEntity> ORCIDRequestToken(@RequestBody ORCIDRequest orcidRequest) { + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(this.orcidTokenValidator.getAccessToken(orcidRequest)).status(ApiMessageCode.NO_MESSAGE)); + } + @RequestMapping(method = RequestMethod.POST, value = {"/me"}, consumes = "application/json", produces = "application/json") public @ResponseBody ResponseEntity> authMe(Principal principal) throws NullEmailException { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessCustomProvider.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessCustomProvider.java similarity index 85% rename from dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessCustomProvider.java rename to dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessCustomProvider.java index 64aaba361..27e615c76 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessCustomProvider.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessCustomProvider.java @@ -1,4 +1,4 @@ -package eu.eudat.logic.security.customproviders; +package eu.eudat.logic.security.customproviders.B2Access; import eu.eudat.logic.security.validators.b2access.helpers.B2AccessResponseToken; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessCustomProviderImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessCustomProviderImpl.java similarity index 98% rename from dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessCustomProviderImpl.java rename to dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessCustomProviderImpl.java index c8f482023..4a4066fb4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessCustomProviderImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessCustomProviderImpl.java @@ -1,4 +1,4 @@ -package eu.eudat.logic.security.customproviders; +package eu.eudat.logic.security.customproviders.B2Access; import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64; import eu.eudat.logic.security.validators.b2access.helpers.B2AccessResponseToken; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessUser.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessUser.java similarity index 90% rename from dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessUser.java rename to dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessUser.java index f42ce4da9..a1dfcf95a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2AccessUser.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/B2Access/B2AccessUser.java @@ -1,4 +1,4 @@ -package eu.eudat.logic.security.customproviders; +package eu.eudat.logic.security.customproviders.B2Access; /** * Created by ikalyvas on 2/22/2018. diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProvider.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProvider.java new file mode 100644 index 000000000..b98b20af8 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProvider.java @@ -0,0 +1,9 @@ +package eu.eudat.logic.security.customproviders.ORCID; + +import eu.eudat.logic.security.validators.orcid.helpers.ORCIDResponseToken; + +public interface ORCIDCustomProvider { + ORCIDUser getUser(String accessToken); + + ORCIDResponseToken getAccessToken(String code, String redirectUri, String clientId, String clientSecret); +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProviderImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProviderImpl.java new file mode 100644 index 000000000..dc6272ab1 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDCustomProviderImpl.java @@ -0,0 +1,65 @@ +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 map = new LinkedMultiValueMap(); + 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> request = new HttpEntity>(map, headers); + + Map 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; + } + + @Override + public ORCIDUser getUser(String accessToken) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = this.createBearerAuthHeaders(accessToken); + HttpEntity entity = new HttpEntity<>(headers); + + //Map values = restTemplate.exchange(this.environment.getProperty("orcid.login.access_token_url"),); + return null; + } + + private HttpHeaders createBearerAuthHeaders(String accessToken) { + return new HttpHeaders() {{ + String authHeader = "Bearer " + accessToken; + set("Authorization", authHeader); + }}; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDUser.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDUser.java new file mode 100644 index 000000000..b0fa89678 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/customproviders/ORCID/ORCIDUser.java @@ -0,0 +1,38 @@ +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; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/ORCIDTokenValidator.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/ORCIDTokenValidator.java new file mode 100644 index 000000000..8d365a052 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/ORCIDTokenValidator.java @@ -0,0 +1,54 @@ +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.ApiContext; +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; + private ApiContext apiContext; + + @Autowired + public ORCIDTokenValidator(Environment environment, AuthenticationService nonVerifiedUserAuthenticationService, ORCIDCustomProvider orcidCustomProvider, ApiContext apiContext) { + this.environment = environment; + this.nonVerifiedUserAuthenticationService = nonVerifiedUserAuthenticationService; + this.orcidCustomProvider = orcidCustomProvider; + this.apiContext = apiContext; + } + + @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")); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDRequest.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDRequest.java new file mode 100644 index 000000000..8fb7dc752 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDRequest.java @@ -0,0 +1,12 @@ +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; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDResponseToken.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDResponseToken.java new file mode 100644 index 000000000..86d7c9f7d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/validators/orcid/helpers/ORCIDResponseToken.java @@ -0,0 +1,28 @@ +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; + } +} diff --git a/dmp-frontend/src/app/core/common/enum/auth-provider.ts b/dmp-frontend/src/app/core/common/enum/auth-provider.ts index c1302645c..460ce2b50 100644 --- a/dmp-frontend/src/app/core/common/enum/auth-provider.ts +++ b/dmp-frontend/src/app/core/common/enum/auth-provider.ts @@ -4,5 +4,6 @@ export enum AuthProvider { Twitter = 3, LinkedIn = 4, //NativeLogin=5, - B2Access = 6 + B2Access = 6, + ORCID = 7 } diff --git a/dmp-frontend/src/app/core/model/orcid/orcidUser.ts b/dmp-frontend/src/app/core/model/orcid/orcidUser.ts new file mode 100644 index 000000000..5642ee8fb --- /dev/null +++ b/dmp-frontend/src/app/core/model/orcid/orcidUser.ts @@ -0,0 +1,5 @@ +export class OrcidUser { + orcidId: string; + name: string; + email: string; +} diff --git a/dmp-frontend/src/app/ui/auth/login/img/ORCIDiD_medium.png b/dmp-frontend/src/app/ui/auth/login/img/ORCIDiD_medium.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb97949b1b29be723ef22c5cfebd5692de73942 GIT binary patch literal 1542 zcmbVMZA=qq9Dhm?6y!x+Ht>ZV2g!(|y}Q0$@1WSyYo(F03SC6!2-n_0FSNbmdO)pg zqc{|zb2CGS%9z>wuq^XEF*6tk1LKS?;zlyWnCR5udeZj$^BMIsO7C0nvpOI3WG)Iy6aurR!bg&YC8 zo~>kQW<%pywip0q9p|o=s-5Memk+4vn2tIe5M(p}#Vf)B?QLKs$ivoiK@&XL|1}J8 zj0s+&ccMkgO_076(vw{n3M?utVBcMfIk=_!zOr|mz4LhV+4k# zRip+J{M4yxrwg+3A`9u&sLG2PP{@F(F|7{A@j^(0Vkm-Y5KN=Oa8j!wQ52eaVA-0; z)RC2xea4n7nP8tJ2_%BFw6v&Ov}#_gM=*jQVjLQcO4d+?HUuR)tO|zm;tUiU@`{`w zaeNSpG14BsNixB*r%yu&2u|lS;$UbdQF6+VFfAaM8btzuSX|TEA*qu6*Ns`VL+%X% zi&U~9zDe}T^{C5>gXP>k-%w0Z_J({-gUL~$dEVYm*( zHK@Ue$>Hm)gjSDf?FPzX)Z=lE*{}x6s@LkQdb?eZW0(yy;ufQ=)Mzx=@lq>=5^<~} z7?S9qmyO%yWVjDC zu(kW*RO)cgxw3ap&oeK7xic-RObI2ICz6a}Z8})@CD{M-^(oa6@WS#g^Oj<0Twy+^ z+_x(gbtSj9kshTb*}SQ>L>Vx{k#5v8^(ew%SWaG2V~rJkJUYb9@Acp9CgDsXzvu8U zv9$HcZ;SjVwo{s{s(I(PjCb4y%g+!cP}|+r_SUKN6osf*uzF5KMxm>sME&}M(p?1{ zcyoUCUw{7EaqaKlFV8=8s#jUm*Oq5)R@X*%3C7gy>c!?}a5T$s|IXw~n;%ae*Yv(^ z+!@{dC_~LALH%p@oql!g)jNkK%v+D=!XH)bv}AUkxRjqgY8x6PZrvDqQTY5SP!x_F z{kS~&Bt;WQR4n-p?xypH}bfm^Z%pvx66+H`_kE?fz<#KULGU>KBX4lK92mJ7R$MhVoA06z?$0Kt!8spXIXo`F2kXYpU6_d8Sl{kpMmH~7y@wfa zjlEw}_`_k70B&tunYn4si6|JJ*ztzV?R#>~pX=>bjx=wCm+fH+-b(ClpF6(Jx&O$` qB}px37?<>2l5L{9=1QmyD8aG!?$vz1{^7~kpV?unpbnPSw*LbY#2sM( literal 0 HcmV?d00001 diff --git a/dmp-frontend/src/app/ui/auth/login/login.component.html b/dmp-frontend/src/app/ui/auth/login/login.component.html index fb95f292e..49082dde1 100644 --- a/dmp-frontend/src/app/ui/auth/login/login.component.html +++ b/dmp-frontend/src/app/ui/auth/login/login.component.html @@ -2,23 +2,32 @@