From e51d1ef8d647564af2e14cf89a980c67634c5d9e Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Tue, 17 Jan 2017 18:43:20 -0500 Subject: [PATCH 1/5] Refactor GoogleAuthenticatorChallenge to allow for setting code along with challenge. --- .../google/GoogleAuthenticatorChallenge.java | 9 ++++- .../google/GoogleAuthenticatorChallenges.java | 8 ++--- ...leAuthenticatorCreateChallengeRequest.java | 5 +++ ...nticatorCreateChallengeRequestBuilder.java | 8 +++++ .../GoogleAuthenticatorChallengeIT.groovy | 34 ++++++++++++++++--- .../sdk/impl/challenge/AbstractChallenge.java | 9 ++--- .../DefaultCreateChallengeRequestBuilder.java | 6 ++-- .../DefaultGoogleAuthenticatorChallenge.java | 7 +++- ...leAuthenticatorCreateChallengeRequest.java | 13 +++++++ ...nticatorCreateChallengeRequestBuilder.java | 24 +++++++++++++ 10 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java create mode 100644 api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java create mode 100644 impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java create mode 100644 impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenge.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenge.java index 6a0d54afe2..5e30f866f9 100644 --- a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenge.java +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenge.java @@ -29,6 +29,13 @@ * * @since 1.1.0 */ -public interface GoogleAuthenticatorChallenge extends Challenge{ +public interface GoogleAuthenticatorChallenge extends Challenge { + /** + * A GoogleAuthenticatorChallenge can be validated at the same time the challenge is created by setting the code on the challenge. + * + * @param code the code the validated at the same time the GoogleAuthenticatorChallenge is created + * @since 1.4.0 + */ + void setCode(String code); } diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenges.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenges.java index 15b9d5d83a..4774954a1a 100644 --- a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenges.java +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorChallenges.java @@ -58,7 +58,7 @@ public final class GoogleAuthenticatorChallenges extends Challenges { } private static final Class BUILDER_CLASS = - Classes.forName("com.stormpath.sdk.impl.challenge.DefaultCreateChallengeRequestBuilder"); + Classes.forName("com.stormpath.sdk.impl.challenge.google.DefaultGoogleAuthenticatorCreateChallengeRequestBuilder"); //Prevent instantiation outside of outer class. //Use getInstance() to retrieve the singleton instance. @@ -152,9 +152,9 @@ public static EqualsExpressionFactory status() { * * @since 1.1.0 */ - public static CreateChallengeRequestBuilder newCreateRequestFor(GoogleAuthenticatorChallenge challenge) { - Constructor ctor = Classes.getConstructor(BUILDER_CLASS, Challenge.class); - return (CreateChallengeRequestBuilder) Classes.instantiate(ctor, challenge); + public static GoogleAuthenticatorCreateChallengeRequestBuilder newCreateRequestFor(GoogleAuthenticatorChallenge challenge) { + Constructor ctor = Classes.getConstructor(BUILDER_CLASS, GoogleAuthenticatorChallenge.class); + return (GoogleAuthenticatorCreateChallengeRequestBuilder) Classes.instantiate(ctor, challenge); } private static EqualsExpressionFactory newEqualsExpressionFactory(String propName) { diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java new file mode 100644 index 0000000000..4e912eda4c --- /dev/null +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java @@ -0,0 +1,5 @@ +package com.stormpath.sdk.challenge.google; + +import com.stormpath.sdk.challenge.CreateChallengeRequest; + +public interface GoogleAuthenticatorCreateChallengeRequest extends CreateChallengeRequest {} diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java new file mode 100644 index 0000000000..bd78ffeeff --- /dev/null +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java @@ -0,0 +1,8 @@ +package com.stormpath.sdk.challenge.google; + +import com.stormpath.sdk.challenge.CreateChallengeRequestBuilder; + +public interface GoogleAuthenticatorCreateChallengeRequestBuilder extends CreateChallengeRequestBuilder { + + GoogleAuthenticatorCreateChallengeRequestBuilder withCode(String code); +} diff --git a/extensions/httpclient/src/test/groovy/com/stormpath/sdk/impl/challenge/GoogleAuthenticatorChallengeIT.groovy b/extensions/httpclient/src/test/groovy/com/stormpath/sdk/impl/challenge/GoogleAuthenticatorChallengeIT.groovy index 3e8765f9da..b48114f3ed 100644 --- a/extensions/httpclient/src/test/groovy/com/stormpath/sdk/impl/challenge/GoogleAuthenticatorChallengeIT.groovy +++ b/extensions/httpclient/src/test/groovy/com/stormpath/sdk/impl/challenge/GoogleAuthenticatorChallengeIT.groovy @@ -43,7 +43,7 @@ import static org.testng.Assert.assertNotNull class GoogleAuthenticatorChallengeIT extends AbstractMultiFactorIT { @Test - void testSuccessfulGoogleAuthenticatorChallenge() { + void testSuccessfulGoogleAuthenticatorChallengeWithCode() { Directory dir = client.instantiate(Directory) dir.name = uniquify("Java SDK: ${this.getClass().getSimpleName()}.${new Object(){}.getClass().getEnclosingMethod().getName()}") dir = client.currentTenant.createDirectory(dir); @@ -60,6 +60,24 @@ class GoogleAuthenticatorChallengeIT extends AbstractMultiFactorIT { assertGoogleAuthenticatorChallengeResponse(factor, getCurrentValidCode(factor), 'SUCCESS') } + @Test + void testSuccessfulGoogleAuthenticatorChallengeTwoStep() { + Directory dir = client.instantiate(Directory) + dir.name = uniquify("Java SDK: ${this.getClass().getSimpleName()}.${new Object(){}.getClass().getEnclosingMethod().getName()}") + dir = client.currentTenant.createDirectory(dir); + deleteOnTeardown(dir) + Account account = createTempAccountInDir(dir) + + def randomAccountName = uniquify("Random Account Name") + def randomIssuer = uniquify("Random Issuer") + def factor = createGoogleAuthenticatorFactor(account, randomIssuer, randomAccountName) + assertGoogleAuthenticatorFactorFields(factor, randomIssuer, randomAccountName) + + sleepToAvoidCrossingThirtySecondMark() + + GoogleAuthenticatorChallenge challenge = createChallengeWithCode(factor) + assertTrue challenge.validate(getCurrentValidCode(factor)) + } @Test void testGoogleAuthenticatorChallengeWithGarbageCode() { @@ -75,7 +93,7 @@ class GoogleAuthenticatorChallengeIT extends AbstractMultiFactorIT { Throwable e = null try { - createChallenge(factor, "bogus") + createChallengeWithCode(factor, "bogus") } catch (ResourceException re) { e = re assertEquals(re.status, 400) @@ -98,7 +116,7 @@ class GoogleAuthenticatorChallengeIT extends AbstractMultiFactorIT { Throwable e = null try { - createChallenge(factor, "123456") + createChallengeWithCode(factor, "123456") } catch (ResourceException re) { e = re assertEquals(re.status, 400) @@ -127,7 +145,7 @@ class GoogleAuthenticatorChallengeIT extends AbstractMultiFactorIT { private void assertGoogleAuthenticatorChallengeResponse(GoogleAuthenticatorFactor factor, String code, String status, String verificationStatus = 'VERIFIED') { String factorHref = factor.href - GoogleAuthenticatorChallenge challenge = createChallenge(factor, code) + GoogleAuthenticatorChallenge challenge = createChallengeWithCode(factor, code) assertInitialChallengeFields(challenge, status, false) FactorOptions options = Factors.options().withChallenges().withMostRecentChallenge() @@ -182,13 +200,19 @@ class GoogleAuthenticatorChallengeIT extends AbstractMultiFactorIT { sleep(secondsToWait * 1000) } - private GoogleAuthenticatorChallenge createChallenge(GoogleAuthenticatorFactor factor, String code = null) { + private GoogleAuthenticatorChallenge createChallengeWithCode(GoogleAuthenticatorFactor factor, String code = null) { def challenge = client.instantiate(GoogleAuthenticatorChallenge.class) challenge.setCode(code) ChallengeOptions options = Challenges.GOOGLE_AUTHENTICATOR.options().withFactor() return factor.createChallenge(Challenges.GOOGLE_AUTHENTICATOR.newCreateRequestFor(challenge).withResponseOptions(options).build()) } + private GoogleAuthenticatorChallenge createChallengeWithoutCode(GoogleAuthenticatorFactor factor) { + def challenge = client.instantiate(GoogleAuthenticatorChallenge.class) + ChallengeOptions options = Challenges.GOOGLE_AUTHENTICATOR.options().withFactor() + return factor.createChallenge(Challenges.GOOGLE_AUTHENTICATOR.newCreateRequestFor(challenge).withResponseOptions(options).build()) + } + private String getCurrentValidCode(GoogleAuthenticatorFactor factor) { return getCurrentCode(factor, true) } diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/AbstractChallenge.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/AbstractChallenge.java index d718282941..5fdc758834 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/AbstractChallenge.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/AbstractChallenge.java @@ -31,7 +31,7 @@ public abstract class AbstractChallenge extends AbstractInstanceResource implements Challenge { public static final EnumProperty STATUS = new EnumProperty<>("status", Enum.class); - static final StringProperty CODE = new StringProperty("code"); + public static final StringProperty CODE = new StringProperty("code"); static final ResourceReference ACCOUNT = new ResourceReference<>("account", Account.class); static final ResourceReference FACTOR = new ResourceReference<>("factor", Factor.class); public static final DateProperty CREATED_AT = new DateProperty("createdAt"); @@ -92,16 +92,11 @@ public Challenge setFactor(T factor) { @Override public boolean validate(String code) { Assert.notNull(code, "code can not be null."); - setCode(code); + setProperty(CODE, code); Challenge returnedChallenge = getDataStore().create(getHref(), this); if ((returnedChallenge.getStatus()).name().equals("SUCCESS")) { return true; } return false; } - - protected Challenge setCode(String code) { - setProperty(CODE, code); - return this; - } } diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/DefaultCreateChallengeRequestBuilder.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/DefaultCreateChallengeRequestBuilder.java index 5ee8e9de20..093405c341 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/DefaultCreateChallengeRequestBuilder.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/DefaultCreateChallengeRequestBuilder.java @@ -24,10 +24,10 @@ /** * @since 1.1.0 */ -public class DefaultCreateChallengeRequestBuilder implements CreateChallengeRequestBuilder { +public class DefaultCreateChallengeRequestBuilder implements CreateChallengeRequestBuilder { - private final T challenge; - private ChallengeOptions options; + protected final T challenge; + protected ChallengeOptions options; public DefaultCreateChallengeRequestBuilder(T challenge) { Assert.notNull(challenge, "Challenge can't be null."); diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorChallenge.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorChallenge.java index 843120c1fc..ff7c8b170c 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorChallenge.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorChallenge.java @@ -27,7 +27,7 @@ /** * @since 1.1.0 */ -public class DefaultGoogleAuthenticatorChallenge extends AbstractChallenge implements GoogleAuthenticatorChallenge{ +public class DefaultGoogleAuthenticatorChallenge extends AbstractChallenge implements GoogleAuthenticatorChallenge { static final Map PROPERTY_DESCRIPTORS = AbstractChallenge.PROPERTY_DESCRIPTORS; @@ -53,4 +53,9 @@ public GoogleAuthenticatorChallengeStatus getStatus() { } return GoogleAuthenticatorChallengeStatus.valueOf(value.toUpperCase()); } + + @Override + public void setCode(String code) { + setProperty(CODE, code); + } } diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java new file mode 100644 index 0000000000..47f2aa8d77 --- /dev/null +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java @@ -0,0 +1,13 @@ +package com.stormpath.sdk.impl.challenge.google; + +import com.stormpath.sdk.challenge.Challenge; +import com.stormpath.sdk.challenge.ChallengeOptions; +import com.stormpath.sdk.challenge.google.GoogleAuthenticatorCreateChallengeRequest; +import com.stormpath.sdk.impl.challenge.DefaultCreateChallengeRequest; + +public class DefaultGoogleAuthenticatorCreateChallengeRequest extends DefaultCreateChallengeRequest implements GoogleAuthenticatorCreateChallengeRequest { + + public DefaultGoogleAuthenticatorCreateChallengeRequest(Challenge challenge, ChallengeOptions options) { + super(challenge, options); + } +} diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java new file mode 100644 index 0000000000..1a365a4126 --- /dev/null +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java @@ -0,0 +1,24 @@ +package com.stormpath.sdk.impl.challenge.google; + +import com.stormpath.sdk.challenge.google.GoogleAuthenticatorCreateChallengeRequest; +import com.stormpath.sdk.challenge.google.GoogleAuthenticatorChallenge; +import com.stormpath.sdk.challenge.google.GoogleAuthenticatorCreateChallengeRequestBuilder; +import com.stormpath.sdk.impl.challenge.DefaultCreateChallengeRequestBuilder; + +public class DefaultGoogleAuthenticatorCreateChallengeRequestBuilder extends DefaultCreateChallengeRequestBuilder implements GoogleAuthenticatorCreateChallengeRequestBuilder { + + public DefaultGoogleAuthenticatorCreateChallengeRequestBuilder(GoogleAuthenticatorChallenge challenge) { + super(challenge); + } + + @Override + public GoogleAuthenticatorCreateChallengeRequestBuilder withCode(String code) { + challenge.setCode(code); + return this; + } + + @Override + public GoogleAuthenticatorCreateChallengeRequest build() { + return new DefaultGoogleAuthenticatorCreateChallengeRequest(challenge, options); + } +} From 9fd663960ac7964fac3909c9dcb2468888da5125 Mon Sep 17 00:00:00 2001 From: Richard Blaylock Date: Tue, 17 Jan 2017 18:00:10 -0800 Subject: [PATCH 2/5] Add missing license headers. --- ...GoogleAuthenticatorCreateChallengeRequest.java | 15 +++++++++++++++ ...uthenticatorCreateChallengeRequestBuilder.java | 15 +++++++++++++++ ...GoogleAuthenticatorCreateChallengeRequest.java | 15 +++++++++++++++ ...uthenticatorCreateChallengeRequestBuilder.java | 15 +++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java index 4e912eda4c..6370590857 100644 --- a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2016 Stormpath, Inc. + * + * Licensed 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 com.stormpath.sdk.challenge.google; import com.stormpath.sdk.challenge.CreateChallengeRequest; diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java index bd78ffeeff..2bdc62d27e 100644 --- a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2016 Stormpath, Inc. + * + * Licensed 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 com.stormpath.sdk.challenge.google; import com.stormpath.sdk.challenge.CreateChallengeRequestBuilder; diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java index 47f2aa8d77..6a9caeb94f 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2016 Stormpath, Inc. + * + * Licensed 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 com.stormpath.sdk.impl.challenge.google; import com.stormpath.sdk.challenge.Challenge; diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java index 1a365a4126..1302accfd2 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2016 Stormpath, Inc. + * + * Licensed 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 com.stormpath.sdk.impl.challenge.google; import com.stormpath.sdk.challenge.google.GoogleAuthenticatorCreateChallengeRequest; From 499553ece4f8c580e93044f044b6f528c856b08a Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Tue, 17 Jan 2017 22:00:51 -0500 Subject: [PATCH 3/5] Updated javadocs and licenses per @mrioan --- ...ogleAuthenticatorCreateChallengeRequest.java | 9 ++++++++- ...henticatorCreateChallengeRequestBuilder.java | 14 +++++++++++++- .../google/GoogleAuthenticatorFactor.java | 17 +++++++++++++++-- ...ogleAuthenticatorCreateChallengeRequest.java | 5 ++++- ...henticatorCreateChallengeRequestBuilder.java | 5 ++++- 5 files changed, 44 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java index 6370590857..d7029f8294 100644 --- a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Stormpath, Inc. + * Copyright 2017 Stormpath, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,4 +17,11 @@ import com.stormpath.sdk.challenge.CreateChallengeRequest; +/** + * A Google Authenticator specific create challenge request + * + * Google Authenticator challenges can validate a code at the same time that the challenge is created. + * + * @since 1.4.0 + */ public interface GoogleAuthenticatorCreateChallengeRequest extends CreateChallengeRequest {} diff --git a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java index 2bdc62d27e..ce0dc15f40 100644 --- a/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java +++ b/api/src/main/java/com/stormpath/sdk/challenge/google/GoogleAuthenticatorCreateChallengeRequestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Stormpath, Inc. + * Copyright 2017 Stormpath, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,19 @@ import com.stormpath.sdk.challenge.CreateChallengeRequestBuilder; +/** + * A builder to construct {@link GoogleAuthenticatorCreateChallengeRequest}s Google Authenticator specific create challenge requests. + * + * Google Authenticator can both create the challenge and set the code in one API call. + * See {@link com.stormpath.sdk.factor.google.GoogleAuthenticatorFactor} + * + * @since 1.4.0 + */ public interface GoogleAuthenticatorCreateChallengeRequestBuilder extends CreateChallengeRequestBuilder { + /** + * @param code to be used to validate the challenge for the {@link com.stormpath.sdk.factor.google.GoogleAuthenticatorFactor} + * @return GoogleAuthenticatorCreateChallengeRequestBuilder for method chaining with the builder pattern + */ GoogleAuthenticatorCreateChallengeRequestBuilder withCode(String code); } diff --git a/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java b/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java index 3ee4d49885..07f62c315e 100644 --- a/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java +++ b/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java @@ -22,8 +22,21 @@ * A {@code GoogleAuthenticatorFactor} is a Factor that represents a two-step verification services using * the Time-based One-time Password Algorithm (TOTP) and HMAC-based One-time Password Algorithm (HOTP), * for authenticating users of mobile applications by Google. - * When issuing a challenge via an GoogleAuthenticatorFactor, a code is sent to the Google Authenticator app, - * and the user can enter the received code back into the system to verify/complete the challenge. + *

+ * The TOTP algorithm determines the next valid code without the requirement for any communication between server and + * TOTP client. + *

+ * As such, the challenge can be created with the code at the same time: + *

+ *

+ * GoogleAuthenticatorChallenge challenge = client.instantiate(GoogleAuthenticatorChallenge.class);
+ * challenge = (GoogleAuthenticatorChallenge) googleAuthenticatorFactor.createChallenge(
+ *     Challenges.GOOGLE_AUTHENTICATOR
+ *         .newCreateRequestFor(challenge)
+ *         .withCode(code)
+ *         .build()
+ *     );
+ * 
* * @since 1.1.0 */ diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java index 6a9caeb94f..4b18c2a83a 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Stormpath, Inc. + * Copyright 2017 Stormpath, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,9 @@ import com.stormpath.sdk.challenge.google.GoogleAuthenticatorCreateChallengeRequest; import com.stormpath.sdk.impl.challenge.DefaultCreateChallengeRequest; +/** + * @since 1.4.0 + */ public class DefaultGoogleAuthenticatorCreateChallengeRequest extends DefaultCreateChallengeRequest implements GoogleAuthenticatorCreateChallengeRequest { public DefaultGoogleAuthenticatorCreateChallengeRequest(Challenge challenge, ChallengeOptions options) { diff --git a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java index 1302accfd2..2722d6434b 100644 --- a/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java +++ b/impl/src/main/java/com/stormpath/sdk/impl/challenge/google/DefaultGoogleAuthenticatorCreateChallengeRequestBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Stormpath, Inc. + * Copyright 2017 Stormpath, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,9 @@ import com.stormpath.sdk.challenge.google.GoogleAuthenticatorCreateChallengeRequestBuilder; import com.stormpath.sdk.impl.challenge.DefaultCreateChallengeRequestBuilder; +/** + * @since 1.4.0 + */ public class DefaultGoogleAuthenticatorCreateChallengeRequestBuilder extends DefaultCreateChallengeRequestBuilder implements GoogleAuthenticatorCreateChallengeRequestBuilder { public DefaultGoogleAuthenticatorCreateChallengeRequestBuilder(GoogleAuthenticatorChallenge challenge) { From 4f8b70642fdb8e7a8538b1d1f9e945ab9b7f161d Mon Sep 17 00:00:00 2001 From: Micah Silverman Date: Wed, 18 Jan 2017 11:04:35 -0500 Subject: [PATCH 4/5] Added convenience method to create challenge for Google Authenticator. --- .../google/GoogleAuthenticatorFactor.java | 17 ++++++++++------- .../DefaultGoogleAuthenticatorFactor.java | 8 ++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java b/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java index 07f62c315e..9a0f2e001c 100644 --- a/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java +++ b/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java @@ -28,14 +28,9 @@ *

* As such, the challenge can be created with the code at the same time: *

+ * *

- * GoogleAuthenticatorChallenge challenge = client.instantiate(GoogleAuthenticatorChallenge.class);
- * challenge = (GoogleAuthenticatorChallenge) googleAuthenticatorFactor.createChallenge(
- *     Challenges.GOOGLE_AUTHENTICATOR
- *         .newCreateRequestFor(challenge)
- *         .withCode(code)
- *         .build()
- *     );
+ * GoogleAuthenticatorChallenge challenge = googleAuthenticatorFactor.createChallenge(code);
  * 
* * @since 1.1.0 @@ -93,4 +88,12 @@ public interface GoogleAuthenticatorFactor Date: Wed, 18 Jan 2017 11:38:15 -0500 Subject: [PATCH 5/5] updated 'since' per @mrioan --- .../stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java b/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java index 9a0f2e001c..3d3c380b32 100644 --- a/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java +++ b/api/src/main/java/com/stormpath/sdk/factor/google/GoogleAuthenticatorFactor.java @@ -94,6 +94,7 @@ public interface GoogleAuthenticatorFactor