From f8d9541abdb49f824b47f20592f9add8b39164f0 Mon Sep 17 00:00:00 2001 From: Ruben Andreassen Date: Mon, 4 Dec 2017 13:49:05 +0000 Subject: [PATCH] Dataporten --- src/main/java/Bundle.properties | 5 + .../AuthenticationServiceBean.java | 5 +- .../AbstractOAuth2AuthenticationProvider.java | 1 + .../OAuth2AuthenticationProviderFactory.java | 2 + .../oauth2/OAuth2FirstLoginPage.java | 3 + .../providers/oauth2/impl/DataportenApi.java | 45 +++++++ .../oauth2/impl/DataportenOAuth2AP.java | 115 ++++++++++++++++++ 7 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenApi.java create mode 100644 src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenOAuth2AP.java diff --git a/src/main/java/Bundle.properties b/src/main/java/Bundle.properties index f8b49a9b033..e9b1f43902f 100755 --- a/src/main/java/Bundle.properties +++ b/src/main/java/Bundle.properties @@ -255,16 +255,20 @@ auth.providers.title.shib=Your Institution auth.providers.title.orcid=ORCID auth.providers.title.google=Google auth.providers.title.github=GitHub +auth.providers.title.dataporten=Dataporten auth.providers.blurb=Log in or sign up with your {0} account — learn more. Having trouble? Please contact {3} for assistance. auth.providers.persistentUserIdName.orcid=ORCID iD auth.providers.persistentUserIdName.github=ID +auth.providers.persistentUserIdName.dataporten=ID auth.providers.persistentUserIdTooltip.orcid=ORCID provides a persistent digital identifier that distinguishes you from other researchers. auth.providers.persistentUserIdTooltip.github=GitHub assigns a unique number to every user. +auth.providers.persistentUserIdTooltip.dataporten=Dataporten assigns a unique number to every user. auth.providers.orcid.insufficientScope=Dataverse was not granted the permission to read user data from ORCID. # Friendly AuthenticationProvider names authenticationProvider.name.builtin=Dataverse authenticationProvider.name.null=(provider is unknown) authenticationProvider.name.github=GitHub +authenticationProvider.name.dataporten=Dataporten authenticationProvider.name.google=Google authenticationProvider.name.orcid=ORCiD authenticationProvider.name.orcid-sandbox=ORCiD Sandbox @@ -1698,6 +1702,7 @@ citationFrame.banner.countdownMessage.seconds=seconds authenticationProvider.name.builtin=Dataverse authenticationProvider.name.null=(provider is unknown) authenticationProvider.name.github=GitHub +authenticationProvider.name.dataporten=Dataporten authenticationProvider.name.google=Google authenticationProvider.name.orcid=ORCiD authenticationProvider.name.orcid-sandbox=ORCiD Sandbox diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java index 8eadbe70221..f7e66e071cf 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/AuthenticationServiceBean.java @@ -18,6 +18,7 @@ import edu.harvard.iq.dataverse.authorization.providers.oauth2.AbstractOAuth2AuthenticationProvider; import edu.harvard.iq.dataverse.authorization.providers.oauth2.OAuth2AuthenticationProviderFactory; import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.GitHubOAuth2AP; +import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.DataportenOAuth2AP; import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.GoogleOAuth2AP; import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.OrcidOAuth2AP; import edu.harvard.iq.dataverse.authorization.providers.shib.ShibAuthenticationProvider; @@ -863,6 +864,7 @@ public AuthenticatedUser canLogInAsBuiltinUser(String username, String password) */ public List getAuthenticationProviderIdsSorted() { GitHubOAuth2AP github = new GitHubOAuth2AP(null, null); + DataportenOAuth2AP dataporten = new DataportenOAuth2AP(null, null); GoogleOAuth2AP google = new GoogleOAuth2AP(null, null); return Arrays.asList( BuiltinAuthenticationProvider.PROVIDER_ID, @@ -870,7 +872,8 @@ public List getAuthenticationProviderIdsSorted() { OrcidOAuth2AP.PROVIDER_ID_PRODUCTION, OrcidOAuth2AP.PROVIDER_ID_SANDBOX, github.getId(), - google.getId() + google.getId(), + dataporten.getId() ); } diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/AbstractOAuth2AuthenticationProvider.java b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/AbstractOAuth2AuthenticationProvider.java index 8cfb84e7ce3..22f704715b7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/AbstractOAuth2AuthenticationProvider.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/AbstractOAuth2AuthenticationProvider.java @@ -236,5 +236,6 @@ public enum DevOAuthAccountType { RANDOM_EMAIL1, RANDOM_EMAIL2, RANDOM_EMAIL3, + RANDOM_EMAIL4, }; } diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2AuthenticationProviderFactory.java b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2AuthenticationProviderFactory.java index eebe87dea97..2381a0d5611 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2AuthenticationProviderFactory.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2AuthenticationProviderFactory.java @@ -5,6 +5,7 @@ import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderFactory; import edu.harvard.iq.dataverse.authorization.providers.AuthenticationProviderRow; import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.GitHubOAuth2AP; +import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.DataportenOAuth2AP; import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.GoogleOAuth2AP; import edu.harvard.iq.dataverse.authorization.providers.oauth2.impl.OrcidOAuth2AP; import java.util.Arrays; @@ -29,6 +30,7 @@ private static interface ProviderBuilder { public OAuth2AuthenticationProviderFactory() { builders.put("github", (row, data) -> readRow(row, new GitHubOAuth2AP(data.get("clientId"), data.get("clientSecret")))); + builders.put("dataporten", (row, data) -> readRow(row, new DataportenOAuth2AP(data.get("clientId"), data.get("clientSecret")))); builders.put("google", (row, data) -> readRow(row, new GoogleOAuth2AP(data.get("clientId"), data.get("clientSecret")))); builders.put("orcid", (row, data) -> readRow(row, new OrcidOAuth2AP(data.get("clientId"), data.get("clientSecret"), data.get("userEndpoint")))); } diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2FirstLoginPage.java b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2FirstLoginPage.java index 9ca92466465..28d48e27a55 100644 --- a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2FirstLoginPage.java +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/OAuth2FirstLoginPage.java @@ -134,6 +134,9 @@ public void init() throws IOException { extraEmails.add("extra1@example.com"); extraEmails.add("extra2@example.com"); break; + case RANDOM_EMAIL4: + authProviderId = "dataporten"; + break; default: break; } diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenApi.java b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenApi.java new file mode 100644 index 00000000000..3a5d04a2ca6 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenApi.java @@ -0,0 +1,45 @@ +package edu.harvard.iq.dataverse.authorization.providers.oauth2.impl; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Verb; + +/** + * + * @author ran033@uit.no (Ruben Andreassen) + */ +public class DataportenApi extends DefaultApi20 { + + protected DataportenApi() { + } + + private static class InstanceHolder { + private static final DataportenApi INSTANCE = new DataportenApi(); + } + + public static DataportenApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.POST; + } + + @Override + public String getAccessTokenEndpoint() { + return "https://auth.dataporten.no/oauth/token"; + } + + @Override + protected String getAuthorizationBaseUrl() { + return "https://auth.dataporten.no/oauth/authorization"; + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenOAuth2AP.java b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenOAuth2AP.java new file mode 100644 index 00000000000..24f9853af47 --- /dev/null +++ b/src/main/java/edu/harvard/iq/dataverse/authorization/providers/oauth2/impl/DataportenOAuth2AP.java @@ -0,0 +1,115 @@ +package edu.harvard.iq.dataverse.authorization.providers.oauth2.impl; + +// Dataporten is a part of ScribeJava in the future https://github.com/scribejava/scribejava/pull/805 +// import com.github.scribejava.apis.DataportenApi; //Uncomment and delete DataportenApi.java when ScribeJava is updated in Maven +import com.github.scribejava.core.builder.api.BaseApi; +import edu.emory.mathcs.backport.java.util.Collections; +import edu.harvard.iq.dataverse.authorization.AuthenticatedUserDisplayInfo; +import edu.harvard.iq.dataverse.authorization.providers.oauth2.AbstractOAuth2AuthenticationProvider; +import edu.harvard.iq.dataverse.authorization.providers.shib.ShibUserNameFields; +import edu.harvard.iq.dataverse.authorization.providers.shib.ShibUtil; +import edu.harvard.iq.dataverse.util.BundleUtil; +import java.io.StringReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonReader; +import javax.json.JsonArray; + +/** + * + * @author ran033@uit.no (Ruben Andreassen) + */ +public class DataportenOAuth2AP extends AbstractOAuth2AuthenticationProvider { + + public DataportenOAuth2AP(String aClientId, String aClientSecret) { + id = "dataporten"; + title = BundleUtil.getStringFromBundle("auth.providers.title.dataporten"); + clientId = aClientId; + clientSecret = aClientSecret; + baseUserEndpoint = "https://auth.dataporten.no/userinfo"; + } + + @Override + public BaseApi getApiInstance() { + return DataportenApi.instance(); + } + + @Override + protected ParsedUserResponse parseUserResponse( String responseBody ) { + + try ( StringReader rdr = new StringReader(responseBody); + JsonReader jrdr = Json.createReader(rdr) ) { + JsonObject responseObject = jrdr.readObject(); + JsonObject userObject = responseObject.getJsonObject("user"); + JsonArray userid_secArray = userObject.getJsonArray("userid_sec"); + + String username = ""; + + /* + Example reponse + { + "user": { + "userid": "76a7a061-3c55-430d-8ee0-6f82ec42501f", + "userid_sec": ["feide:andreas@uninett.no"], + "name": "Andreas \u00c5kre Solberg", + "email": "andreas.solberg@uninett.no", + "profilephoto": "p:a3019954-902f-45a3-b4ee-bca7b48ab507" + }, + "audience": "e8160a77-58f8-4006-8ee5-ab64d17a5b1e" + } + */ + + // Extract ad username using regexp + Pattern p = Pattern.compile("^feide:([0-9a-zA-Z]+?)@.*$"); + Matcher m = p.matcher(userid_secArray.getString(0)); + if(m.matches()) { + username = m.group(1); + } + + ShibUserNameFields shibUserNameFields = ShibUtil.findBestFirstAndLastName(null, null, userObject.getString("name","")); + AuthenticatedUserDisplayInfo displayInfo = new AuthenticatedUserDisplayInfo( + shibUserNameFields.getFirstName(), + shibUserNameFields.getLastName(), + userObject.getString("email",""), + "", //company + "" + ); + + return new ParsedUserResponse( + displayInfo, + userObject.getString("userid"), //persistentUserId + username, //username + displayInfo.getEmailAddress().length()>0 ? Collections.singletonList(displayInfo.getEmailAddress()) + : Collections.emptyList() ); + + } + + } + + @Override + public boolean isDisplayIdentifier() { + return false; + } + + @Override + public String getPersistentIdName() { + return BundleUtil.getStringFromBundle("auth.providers.persistentUserIdName.dataporten"); + } + + @Override + public String getPersistentIdDescription() { + return BundleUtil.getStringFromBundle("auth.providers.persistentUserIdTooltip.dataporten"); + } + + @Override + public String getPersistentIdUrlPrefix() { + return null; + } + + @Override + public String getLogo() { + return null; + } +}