Skip to content

Commit 0044dcc

Browse files
author
Michael Mroz
committed
Exposed OTP secret for not-yet serialised Transaction entities
1 parent f0f21d7 commit 0044dcc

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

src/main/java/com/auth0/guardian/Transaction.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ public class Transaction implements Serializable {
4040

4141
private String transactionToken;
4242
private String recoveryCode;
43-
private transient String otpSecret;
43+
private transient String totpSecret;
4444

45-
Transaction(String transactionToken, String recoveryCode, String otpSecret) {
45+
Transaction(String transactionToken, String recoveryCode, String totpSecret) {
4646
this.transactionToken = transactionToken;
4747
this.recoveryCode = recoveryCode;
48-
this.otpSecret = otpSecret;
48+
this.totpSecret = totpSecret;
4949
}
5050

5151
public String getTransactionToken() {
@@ -56,6 +56,21 @@ public String getRecoveryCode() {
5656
return recoveryCode;
5757
}
5858

59+
/**
60+
* Returns the TOTP secret to be encoded in a URI for QR code generation,
61+
* or manually entered if a camera is not available to the enrollment device.
62+
*
63+
* @return the TOTP secret
64+
* @throws IllegalStateException when there is no OTP secret
65+
*/
66+
public String getTotpSecret() throws IllegalStateException {
67+
if (totpSecret == null) {
68+
throw new IllegalStateException("There is no OTP Secret for this transaction");
69+
}
70+
71+
return totpSecret;
72+
}
73+
5974
/**
6075
* Returns the TOTP enrollment URI to be displayed in the QR code
6176
*
@@ -65,16 +80,12 @@ public String getRecoveryCode() {
6580
* @throws IllegalStateException when there is no OTP secret
6681
*/
6782
public String totpURI(String user, String issuer) throws IllegalStateException {
68-
if (otpSecret == null) {
69-
throw new IllegalStateException("There is no OTP Secret for this transaction");
70-
}
71-
7283
// use HttpUrl to build the URI, java.net.URL really sucks
7384
return new HttpUrl.Builder()
7485
.scheme("https") // HttpUrl only allows http/https so I replace it afterwards
7586
.host("totp")
7687
.addPathSegment(String.format("%s:%s", issuer, user))
77-
.addQueryParameter("secret", otpSecret)
88+
.addQueryParameter("secret", getTotpSecret())
7889
.addQueryParameter("issuer", issuer)
7990
.build()
8091
.toString()

src/test/java/com/auth0/guardian/GuardianTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public void shouldRequestEnrollWithTOTP() throws Exception {
9898
assertThat(transaction, is(notNullValue()));
9999
assertThat(transaction.getTransactionToken(), is(equalTo("THE_TRANSACTION_TOKEN")));
100100
assertThat(transaction.getRecoveryCode(), is(equalTo("THE_RECOVERY_CODE")));
101+
assertThat(transaction.getTotpSecret(), is(equalTo("THE_OTP_SECRET")));
101102
assertThat(transaction.totpURI("user", "issuer"), is(equalTo("otpauth://totp/issuer:user?secret=THE_OTP_SECRET&issuer=issuer")));
102103
}
103104

@@ -130,6 +131,7 @@ public void shouldRequestEnrollWithSMS() throws Exception {
130131
assertThat(transaction, is(notNullValue()));
131132
assertThat(transaction.getTransactionToken(), is(equalTo("THE_TRANSACTION_TOKEN")));
132133
assertThat(transaction.getRecoveryCode(), is(equalTo("THE_RECOVERY_CODE")));
134+
assertThat(transaction.getTotpSecret(), is(equalTo("THE_OTP_SECRET")));
133135
assertThat(transaction.totpURI("user", "issuer"), is(equalTo("otpauth://totp/issuer:user?secret=THE_OTP_SECRET&issuer=issuer")));
134136
}
135137

src/test/java/com/auth0/guardian/TransactionTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public void shouldCreateCorrectly() throws Exception {
4646

4747
assertThat(transaction.getTransactionToken(), is(equalTo("TRANSACTION_TOKEN")));
4848
assertThat(transaction.getRecoveryCode(), is(equalTo("RECOVERY_CODE")));
49+
assertThat(transaction.getTotpSecret(), is(equalTo("OTP_SECRET")));
4950
assertThat(transaction.totpURI("username", "company"), is(equalTo("otpauth://totp/company:username?secret=OTP_SECRET&issuer=company")));
5051
}
5152

@@ -55,6 +56,7 @@ public void shouldCreateCorrectlyWithSpaces() throws Exception {
5556

5657
assertThat(transaction.getTransactionToken(), is(equalTo("TRANSACTION_TOKEN")));
5758
assertThat(transaction.getRecoveryCode(), is(equalTo("RECOVERY_CODE")));
59+
assertThat(transaction.getTotpSecret(), is(equalTo("OTP_SECRET")));
5860
assertThat(transaction.totpURI("user name", "company name"), is(equalTo("otpauth://totp/company%20name:user%20name?secret=OTP_SECRET&issuer=company%20name")));
5961
}
6062

@@ -64,6 +66,7 @@ public void shouldCreateCorrectlyWithWeirdCharacters() throws Exception {
6466

6567
assertThat(transaction.getTransactionToken(), is(equalTo("TRANSACTION_TOKEN")));
6668
assertThat(transaction.getRecoveryCode(), is(equalTo("RECOVERY_CODE")));
69+
assertThat(transaction.getTotpSecret(), is(equalTo("OTP_SECRET")));
6770
assertThat(transaction.totpURI("user%name", "compañy?!"), is(equalTo("otpauth://totp/compa%C3%B1y%3F!:user%25name?secret=OTP_SECRET&issuer=compa%C3%B1y?!")));
6871
}
6972

@@ -91,6 +94,32 @@ public void shouldSerializeCorrectly() throws Exception {
9194
assertThat(restoredTransaction.getRecoveryCode(), is(equalTo("RECOVERY_CODE")));
9295
}
9396

97+
@Test
98+
public void shouldThrowWhenRequestingOtpSecretAfterSerialization() throws Exception {
99+
exception.expect(IllegalStateException.class);
100+
exception.expectMessage("There is no OTP Secret for this transaction");
101+
102+
Transaction transaction = new Transaction("TRANSACTION_TOKEN", "RECOVERY_CODE", "OTP_SECRET");
103+
104+
// save
105+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106+
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
107+
objectOutputStream.writeObject(transaction);
108+
objectOutputStream.close();
109+
outputStream.close();
110+
111+
byte[] binaryData = outputStream.toByteArray();
112+
113+
// restore
114+
ByteArrayInputStream inputStream = new ByteArrayInputStream(binaryData);
115+
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
116+
Transaction restoredTransaction = (Transaction) objectInputStream.readObject();
117+
objectInputStream.close();
118+
inputStream.close();
119+
120+
restoredTransaction.getTotpSecret();
121+
}
122+
94123
@Test
95124
public void shouldThrowWhenRequestingTotpUriAfterSerialization() throws Exception {
96125
exception.expect(IllegalStateException.class);

0 commit comments

Comments
 (0)