[java-idp-plugin-totp] branch master updated: POM cleanup and starting on supporting classes.
Scott Cantor
cantor.2 at osu.edu
Thu Jul 9 01:41:57 UTC 2020
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-idp-plugin-totp.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-totp.git;a=commit;h=3c39176020578f2a803cd74d57c20759853d4555
The following commit(s) were added to refs/heads/master by this push:
new 3c39176 POM cleanup and starting on supporting classes.
3c39176 is described below
commit 3c39176020578f2a803cd74d57c20759853d4555
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Jul 8 21:42:04 2020 -0400
POM cleanup and starting on supporting classes.
---
.project | 6 +
pom.xml | 40 +----
totp-dist/pom.xml | 9 +-
totp-dist/src/main/resources/bootstrap/id.property | 1 +
totp-dist/src/main/resources/bootstrap/keys.txt | 189 +++++++++++++++++++++
.../src/main/resources/doc/GoogleAuth-LICENSE.txt | 28 +++
totp-impl/.checkstyle | 10 ++
totp-impl/.project | 6 +
totp-impl/pom.xml | 47 ++++-
.../idp/plugin/totp/context/TOTPContext.java | 171 +++++++++++++++++++
.../idp/plugin/totp/context/package-info.java | 20 +++
.../idp/plugin/totp/impl/AbstractSeedSource.java | 73 ++++++++
.../totp/impl/AttributeResolverSeedSource.java | 133 +++++++++++++++
.../idp/plugin/totp/impl/StaticSeedSource.java | 90 ++++++++++
.../idp/plugin/totp/principal/TOTPPrincipal.java | 89 ++++++++++
.../idp/plugin/totp/principal/package-info.java | 22 +++
16 files changed, 894 insertions(+), 40 deletions(-)
diff --git a/.project b/.project
index 4e300c7..02906e1 100644
--- a/.project
+++ b/.project
@@ -10,8 +10,14 @@
<arguments>
</arguments>
</buildCommand>
+ <buildCommand>
+ <name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
</natures>
</projectDescription>
diff --git a/pom.xml b/pom.xml
index f203230..d1a3386 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,14 +10,15 @@
<version>4.1.0-SNAPSHOT</version>
</parent>
- <name>java-idp-plugin-totp</name>
+ <name>Shibboleth IdP :: Plugins :: TOTP Login Flow</name>
+ <description>An IdP plugin providing TOTP login support.</description>
<groupId>net.shibboleth.idp.plugin</groupId>
- <artifactId>java-idp-plugin-totp</artifactId>
+ <artifactId>idp-plugin-totp</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
- <automatic.module.name>net.shibboleth.idp.plugin.idp-authn-totp</automatic.module.name>
+ <plugin.base>totp</plugin.base>
<idp.groupId>net.shibboleth.idp</idp.groupId>
<idp.version>4.1.0-SNAPSHOT</idp.version>
<checkstyle.configLocation>${project.basedir}/checkstyle.xml</checkstyle.configLocation>
@@ -41,38 +42,11 @@
</repositories>
<scm>
- <connection>scm:git:https://git.shibboleth.net/git/${project.artifactId}</connection>
- <developerConnection>scm:git:git at git.shibboleth.net:${project.artifactId}</developerConnection>
- <url>https://git.shibboleth.net/view/?p=${project.artifactId}.git</url>
+ <connection>scm:git:https://git.shibboleth.net/git/java-${project.artifactId}</connection>
+ <developerConnection>scm:git:git at git.shibboleth.net:java-${project.artifactId}</developerConnection>
+ <url>https://git.shibboleth.net/view/?p=java-${project.artifactId}.git</url>
</scm>
- <dependencies>
- <!-- provided dependencies -->
- <dependency>
- <groupId>net.shibboleth.utilities</groupId>
- <artifactId>java-support</artifactId>
- <version>8.1.0-SNAPSHOT</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>net.shibboleth.ext</groupId>
- <artifactId>spring-extensions</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>${spring-webflow.groupId}</groupId>
- <artifactId>spring-webflow</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>${idp.groupId}</groupId>
- <artifactId>idp-authn-api</artifactId>
- <scope>provided</scope>
- </dependency>
-
- <!-- test dependencies -->
- </dependencies>
-
<dependencyManagement>
<dependencies>
<dependency>
diff --git a/totp-dist/pom.xml b/totp-dist/pom.xml
index 6056c2b..561bd7d 100644
--- a/totp-dist/pom.xml
+++ b/totp-dist/pom.xml
@@ -6,17 +6,18 @@
<parent>
<groupId>net.shibboleth.idp.plugin</groupId>
- <artifactId>java-idp-plugin-totp</artifactId>
+ <artifactId>idp-plugin-totp</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<name>Shibboleth IdP :: Plugins :: TOTP Login Flow Distribution</name>
- <artifactId>idp-plugin-totp-dist</artifactId>
+ <description>IdP TOTP plugin packaging.</description>
+ <artifactId>idp-plugin-${plugin.base}-dist</artifactId>
<packaging>pom</packaging>
<properties>
<checkstyle.configLocation>${project.basedir}/../checkstyle.xml</checkstyle.configLocation>
- <dist.finalName>shibboleth-idp-plugin-totp-${project.version}</dist.finalName>
+ <dist.finalName>shibboleth-idp-plugin-${plugin.base}-${project.version}</dist.finalName>
</properties>
<build>
@@ -36,7 +37,7 @@
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
- <descriptor>src/main/assembly/totp-assembly.xml</descriptor>
+ <descriptor>src/main/assembly/${plugin.base}-assembly.xml</descriptor>
</descriptors>
<finalName>${dist.finalName}</finalName>
<tarLongFileMode>gnu</tarLongFileMode>
diff --git a/totp-dist/src/main/resources/bootstrap/id.property b/totp-dist/src/main/resources/bootstrap/id.property
new file mode 100644
index 0000000..4917477
--- /dev/null
+++ b/totp-dist/src/main/resources/bootstrap/id.property
@@ -0,0 +1 @@
+pluginid=net.shibboleth.idp.plugin.totp
diff --git a/totp-dist/src/main/resources/bootstrap/keys.txt b/totp-dist/src/main/resources/bootstrap/keys.txt
new file mode 100644
index 0000000..0ccc322
--- /dev/null
+++ b/totp-dist/src/main/resources/bootstrap/keys.txt
@@ -0,0 +1,189 @@
+
+pub 4096R/2A4B3FF0 2019-09-18
+uid Rod Widdowson <rdw at steadingsoftware.com>
+sub 4096R/441D628D 2019-09-18
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+HEdQFQ==
+=/gwj
+-----END PGP PUBLIC KEY BLOCK-----
+
+OBS security:shibboleth RPM repository key
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+mQGiBEholYgRBACW/kTYZi5mAEMP8j1qui2bRnWmYblFbiZvb5JMJYUWL/jyMjHj
+LLJvVrnOre/AxexH9KmaJwBuNoa/X9l/tQGIb49QRhR346QQUbQcwlYpckg5ccqN
+qlAURHEdjCxRxMhzPs+C/F6Nqa/fHpAectW0JNRqAVVd9CWjCG3l6I2CywCgk9UI
+SUAvaB5bVMxEVrFAKrVh4MUEAISeUwOaTIZftIamjo0VrnYemHS4SmGqMALEtHeG
+/o7ecMhLb/MvreEVISrE1hbfmnObYoiVXWJrorOEZDh1hOVdGRkHJOYHvQSRp9uC
+/uy4Mmog4R7ba5Ct5wpw0RCav2HMqwOJEyCX6jnip5P5LMmaFdGg/RQZM/e9mbyF
+VeL0A/0WK//+VWrQya1rQIG+v4IZ+rWvrkqXKtrzELkWd/3vWNMXi4BfeBM/itLQ
+yYOdhnx55FHxBzv+dK+UErrdTM8Ingljy7oztV/G6+K15CcGvEy9ITb62v2bDdS2
+uYWEFOQJK+I6aU4paNysvtKsOlTt9FhyfJJW9G3kJDUBPM9HbLRIc2VjdXJpdHk6
+c2hpYmJvbGV0aCBPQlMgUHJvamVjdCA8c2VjdXJpdHk6c2hpYmJvbGV0aEBidWls
+ZC5vcGVuc3VzZS5vcmc+iGYEExECACYFAlgaKTsCGwMFCRPQQ7MGCwkIBwMCBBUC
+CAMEFgIDAQIeAQIXgAAKCRBzyTdFfQobPWC4AJ96FdlQrvlAHzQjqT994h6lZxfZ
+pgCfSBPRhrdNGh72+d288vgZ7ptV4/SIRgQTEQIABgUCSGiViAAKCRA7MBG3a51l
+Iy3vAKCUPurlZup+vzQtpij3FMo0JAVW9ACgjdkt/hWt0WsjfHb+/cPwXtgx9X8=
+=6fV2
+-----END PGP PUBLIC KEY BLOCK-----
+
+Henri Mikkonen PGP key
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+A+i1fd0Gifis1HhBeA==
+=ObHY
+-----END PGP PUBLIC KEY BLOCK-----
+
+philsmart GPG key 4096-bit RSA key, ID C21771DD, created 2020-02-25
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+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
+3aNjQSVwGC4Owz97QpUq9StZb1qhvIw=
+=1e4x
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/totp-dist/src/main/resources/doc/GoogleAuth-LICENSE.txt b/totp-dist/src/main/resources/doc/GoogleAuth-LICENSE.txt
new file mode 100644
index 0000000..9c76b45
--- /dev/null
+++ b/totp-dist/src/main/resources/doc/GoogleAuth-LICENSE.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2013 Warren Strange
+Copyright (c) 2014-2017 Enrico M. Crisostomo
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/totp-impl/.checkstyle b/totp-impl/.checkstyle
new file mode 100644
index 0000000..7c63424
--- /dev/null
+++ b/totp-impl/.checkstyle
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+ <local-check-config name="Shibboleth Checkstyle" location="/java-idp-plugin-totp/checkstyle.xml" type="project" description="">
+ <additional-data name="protect-config-file" value="false"/>
+ </local-check-config>
+ <fileset name="all" enabled="true" check-config-name="Shibboleth Checkstyle" local="true">
+ <file-match-pattern match-pattern="." include-pattern="true"/>
+ </fileset>
+</fileset-config>
diff --git a/totp-impl/.project b/totp-impl/.project
index 96a82b2..8200b02 100644
--- a/totp-impl/.project
+++ b/totp-impl/.project
@@ -15,9 +15,15 @@
<arguments>
</arguments>
</buildCommand>
+ <buildCommand>
+ <name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
</natures>
</projectDescription>
diff --git a/totp-impl/pom.xml b/totp-impl/pom.xml
index efb6daa..0a339a4 100644
--- a/totp-impl/pom.xml
+++ b/totp-impl/pom.xml
@@ -6,20 +6,61 @@
<parent>
<groupId>net.shibboleth.idp.plugin</groupId>
- <artifactId>java-idp-plugin-totp</artifactId>
+ <artifactId>idp-plugin-totp</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<name>Shibboleth IdP :: Plugins :: TOTP Login Flow Impl</name>
- <artifactId>idp-plugin-totp-impl</artifactId>
+ <description>IdP TOTP plugin implementation.</description>
+ <artifactId>idp-plugin-${plugin.base}-impl</artifactId>
<packaging>jar</packaging>
<properties>
<checkstyle.configLocation>${project.basedir}/../checkstyle.xml</checkstyle.configLocation>
- <automatic.module.name>net.shibboleth.idp.plugin.totp.impl</automatic.module.name>
+ <automatic.module.name>net.shibboleth.idp.plugin.${plugin.base}.impl</automatic.module.name>
</properties>
<dependencies>
+ <!-- compile dependencies -->
+ <dependency>
+ <groupId>com.warrenstrange</groupId>
+ <artifactId>googleauth</artifactId>
+ <version>1.5.0</version>
+ </dependency>
+
+ <!-- provided dependencies -->
+ <dependency>
+ <groupId>net.shibboleth.utilities</groupId>
+ <artifactId>java-support</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.shibboleth.ext</groupId>
+ <artifactId>spring-extensions</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${spring-webflow.groupId}</groupId>
+ <artifactId>spring-webflow</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${idp.groupId}</groupId>
+ <artifactId>idp-attribute-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${idp.groupId}</groupId>
+ <artifactId>idp-attribute-resolver-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${idp.groupId}</groupId>
+ <artifactId>idp-authn-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- test dependencies -->
</dependencies>
<build>
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/context/TOTPContext.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/context/TOTPContext.java
new file mode 100644
index 0000000..6a151d5
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/context/TOTPContext.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.totp.context;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.BaseContext;
+
+import com.google.common.base.Strings;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * Context class for state of a TOTP validation.
+ */
+public class TOTPContext extends BaseContext {
+
+ /** Transaction status. */
+ public enum AuthState {
+ /** Success. */
+ OK,
+ /** Failure. */
+ ERROR,
+ /** Unable to locate a token registration. */
+ MISSING_SEED,
+ /** No tokens registered. */
+ REGISTER,
+ /** Unable to validate. */
+ CANT_VALIDATE,
+ /** Unknown. */
+ UNKNOWN,
+ }
+
+ /** State of transaction. */
+ @Nonnull private AuthState state;
+
+ /** The subject identifier with respect to the token "back-end". */
+ @Nullable @NotEmpty private String username;
+
+ /** The token code supplied. */
+ @Nullable private Integer tokenCode;
+
+ /** The token seeds associated with the subject. */
+ @Nonnull @NonnullElements private Collection<String> tokenSeeds;
+
+ /** URL for QR-code. */
+ @Nullable @NotEmpty private String totpURL;
+
+ /** Constructor. */
+ public TOTPContext() {
+ state = AuthState.UNKNOWN;
+ tokenSeeds = new ArrayList<>();
+ }
+
+ /**
+ * Get the state of the transaction.
+ *
+ * @return transaction state
+ */
+ @Nonnull public AuthState getState() {
+ return state;
+ }
+
+
+ /**
+ * Set the state of the transaction.
+ *
+ * @param astate new state
+ *
+ * @return this context
+ */
+ @Nonnull public TOTPContext setState(@Nonnull final AuthState astate) {
+ state = Constraint.isNotNull(astate, "AuthState cannot be null");
+
+ return this;
+ }
+
+ /**
+ * Get the username.
+ *
+ * @return the username
+ */
+ @Nullable @NotEmpty public String getUsername() {
+ return username;
+ }
+
+ /**
+ * Set the username.
+ *
+ * @param name the username
+ *
+ * @return this context
+ */
+ @Nonnull public TOTPContext setUsername(@Nullable @NotEmpty final String name) {
+ if (Strings.isNullOrEmpty(name)) {
+ username = null;
+ } else {
+ username = name;
+ }
+
+ return this;
+ }
+
+ /**
+ * Get the token code.
+ *
+ * @return the token code
+ */
+ @Nullable public Integer getTokenCode() {
+ return tokenCode;
+ }
+
+ /**
+ * Set the token code.
+ *
+ * @param code the token code
+ *
+ * @return this context
+ */
+ @Nonnull public TOTPContext setTokenCode(@Nullable final Integer code) {
+ tokenCode = code;
+
+ return this;
+ }
+
+ /**
+ * Get the token seeds for the subject.
+ *
+ * @return the token seeds
+ */
+ @Nonnull @NonnullElements @Live public Collection<String> getTokenSeeds() {
+ return tokenSeeds;
+ }
+
+ /*
+ //A counter for the numbers of times the user has failed auth in this context
+ private int failedAuth = 0;
+
+
+ public void failedAttempt() {
+ failedAuth++;
+ }
+
+ public int getFailedAttempts(){
+ return failedAuth;
+ }
+ */
+
+}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/context/package-info.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/context/package-info.java
new file mode 100644
index 0000000..11e523f
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/context/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** TOTP login flow context classes. */
+
+package net.shibboleth.idp.plugin.totp.context;
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractSeedSource.java
new file mode 100644
index 0000000..69c116a
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractSeedSource.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.totp.impl;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.plugin.totp.context.TOTPContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+
+/**
+ * Base class for token seed source implementations.
+ */
+ at ThreadSafeAfterInit
+public abstract class AbstractSeedSource extends AbstractInitializableComponent
+ implements Consumer<ProfileRequestContext> {
+
+ /** Lookup strategy for {@link TOTPContext}. */
+ @Nonnull private Function<ProfileRequestContext,TOTPContext> totpContextLookupStrategy;
+
+ /** Constructor. */
+ public AbstractSeedSource() {
+ // PRC -> AuthenticationContext -> TOTPContext
+ totpContextLookupStrategy = FunctionSupport.compose(new ChildContextLookup<>(TOTPContext.class),
+ new ChildContextLookup<>(AuthenticationContext.class));
+ }
+
+ /**
+ * Get the {@link TOTPContext} lookup strategy.
+ *
+ * @return lookup strategy
+ */
+ @Nonnull public Function<ProfileRequestContext,TOTPContext> getTOTPContextLookupStrategy() {
+ return totpContextLookupStrategy;
+ }
+
+ /**
+ * Set the {@link TOTPContext} lookup strategy.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setTOTPContextLookupStrategy(@Nonnull final Function<ProfileRequestContext,TOTPContext> strategy) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ totpContextLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+ }
+
+}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java
new file mode 100644
index 0000000..94ca139
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.totp.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AttributeResolver;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.plugin.totp.context.TOTPContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.service.ReloadableService;
+
+/**
+ * Token seed source implementation that leverages the {@link AttributeResolver}.
+ */
+ at ThreadSafeAfterInit
+public class AttributeResolverSeedSource extends AbstractSeedSource {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AttributeResolverSeedSource.class);
+
+ /** Attribute resolver service. */
+ @NonnullAfterInit private ReloadableService<AttributeResolver> attributeResolver;
+
+ /** Attribute ID to resolve. */
+ @NonnullAfterInit @NotEmpty private String attributeId;
+
+
+ /**
+ * Set the {@link AttributeResolver} to use.
+ *
+ * @param service the resolver
+ */
+ public void setAttributeResolver(@Nonnull final ReloadableService<AttributeResolver> service) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ attributeResolver = Constraint.isNotNull(service, "AttributeResolver cannot be null");
+ }
+
+ /**
+ * Set the source attribute ID to resolve.
+ *
+ * @param id attribute ID
+ */
+ public void setSourceAttribute(@Nonnull @NotEmpty final String id) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ attributeId = Constraint.isNotNull(StringSupport.trimOrNull(id), "Source attribute ID cannot be null or empty");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (attributeResolver == null) {
+ throw new ComponentInitializationException("AttributeResolver cannot be null");
+ } else if (attributeId == null) {
+ throw new ComponentInitializationException("Source attribute ID cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void accept(@Nullable final ProfileRequestContext input) {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+
+ final TOTPContext totp = getTOTPContextLookupStrategy().apply(input);
+ if (totp != null && totp.getUsername() != null) {
+ final AttributeResolutionContext resCtx = totp.getSubcontext(AttributeResolutionContext.class, true);
+
+ resCtx.setResolutionLabel("TOTP");
+ resCtx.setPrincipal(totp.getUsername());
+ resCtx.setRequestedIdPAttributeNames(Collections.singletonList(attributeId));
+
+ log.debug("Resolving attribute {} for '{}'", attributeId, totp.getUsername());
+
+ final Collection<String> seeds = totp.getTokenSeeds();
+
+ try {
+ // Resolve the attributes.
+ resCtx.resolveAttributes(attributeResolver);
+
+ final IdPAttribute attribute = resCtx.getResolvedIdPAttributes().get(attributeId);
+ if (attribute != null) {
+ attribute.getValues()
+ .stream()
+ .filter(StringAttributeValue.class::isInstance)
+ .map(StringAttributeValue.class::cast)
+ .map(StringAttributeValue::getValue)
+ .forEachOrdered(seeds::add);
+ }
+ } finally {
+ totp.removeSubcontext(resCtx);
+ }
+
+ log.debug("Resolved {} seed(s) for '{}'", seeds.size(), totp.getUsername());
+ } else {
+ log.warn("Unable to locate TOTPContext and username");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/StaticSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/StaticSeedSource.java
new file mode 100644
index 0000000..c23eca7
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/StaticSeedSource.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.totp.impl;
+
+import java.util.Collection;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Multimap;
+
+import net.shibboleth.idp.plugin.totp.context.TOTPContext;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.ThreadSafeAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Token seed source implementation that returns statically defined values.
+ */
+ at ThreadSafeAfterInit
+public class StaticSeedSource extends AbstractSeedSource {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(StaticSeedSource.class);
+
+ /** Token seeds. */
+ @Nonnull @NonnullElements private Multimap<String,String> tokenSeeds;
+
+ /** Constructor. */
+ public StaticSeedSource() {
+ tokenSeeds = LinkedListMultimap.create();
+ }
+
+ /**
+ * Set static token seeds, keyed by username.
+ *
+ * @param seeds the seeds
+ */
+ public void setSeeds(@Nonnull @NonnullElements final Map<String,Collection<String>> seeds) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ Constraint.isNotNull(seeds, "Seed map cannot be null");
+
+ seeds.forEach((k,v) -> {
+ final String user = StringSupport.trimOrNull(k);
+ if (user != null) {
+ tokenSeeds.putAll(user, StringSupport.normalizeStringCollection(v));
+ }
+ });
+ }
+
+ /** {@inheritDoc} */
+ public void accept(@Nullable final ProfileRequestContext input) {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+
+ final TOTPContext totp = getTOTPContextLookupStrategy().apply(input);
+ if (totp != null) {
+ if (totp.getUsername() != null) {
+ totp.getTokenSeeds().addAll(tokenSeeds.get(totp.getUsername()));
+ } else {
+ log.warn("TOTPContext did not contain a username");
+ }
+ } else {
+ log.warn("Unable to locate TOTPContext");
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/principal/TOTPPrincipal.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/principal/TOTPPrincipal.java
new file mode 100644
index 0000000..a746f74
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/principal/TOTPPrincipal.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.totp.principal;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.idp.authn.principal.CloneablePrincipal;
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+import com.google.common.base.MoreObjects;
+
+/** Principal based on a TOTP authentication. */
+public class TOTPPrincipal implements CloneablePrincipal {
+
+ /** The username. */
+ @Nonnull @NotEmpty private String username;
+
+ /**
+ * Constructor.
+ *
+ * @param name the username
+ */
+ public TOTPPrincipal(@Nonnull @NotEmpty @ParameterName(name="name") final String name) {
+ username = Constraint.isNotNull(StringSupport.trimOrNull(name), "Username cannot be null or empty");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull @NotEmpty public String getName() {
+ return username;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return username.hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(final Object other) {
+ if (other == null) {
+ return false;
+ }
+
+ if (this == other) {
+ return true;
+ }
+
+ if (other instanceof TOTPPrincipal) {
+ return username.equals(((TOTPPrincipal) other).getName());
+ }
+
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("username", username).toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public TOTPPrincipal clone() throws CloneNotSupportedException {
+ final TOTPPrincipal copy = (TOTPPrincipal) super.clone();
+ copy.username = username;
+ return copy;
+ }
+
+}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/principal/package-info.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/principal/package-info.java
new file mode 100644
index 0000000..ce752fa
--- /dev/null
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/principal/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Custom TOTP principal types.
+ */
+
+package net.shibboleth.idp.plugin.totp.principal;
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list