Skip to content
This repository was archived by the owner on Dec 12, 2018. It is now read-only.

Commit 83c5bd1

Browse files
committed
handling login errors for Okta.
TODO: We may need more general error message mapping between Okta and Stormpath, this is a one off solution
1 parent c804671 commit 83c5bd1

File tree

4 files changed

+70
-22
lines changed

4 files changed

+70
-22
lines changed

extensions/spring/stormpath-spring-security-webmvc/src/main/java/com/stormpath/spring/config/SpringSecurityLoginErrorModelFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public class SpringSecurityLoginErrorModelFactory extends AbstractErrorModelFact
2323
private static final List<String> UNSUCCESSFUL_LOGIN_BACKEND_ERRORS = Arrays.asList(
2424
"Login attempt failed",
2525
"Invalid username or password",
26-
"Login and password required"
26+
"Login and password required",
27+
"invalid_grant" // for Okta
2728
);
2829

2930
@Autowired

extensions/spring/stormpath-spring-security/src/main/java/com/stormpath/spring/security/provider/StormpathAuthenticationProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ private Account handleUsernamePasswordAuthentication(Authentication authenticati
321321
account = application.authenticateAccount(request).getAccount();
322322
} finally {
323323
//Clear the request data to prevent later memory access
324-
// request.clear();
324+
request.clear();
325325
}
326326

327327
return account;

impl/src/main/java/com/stormpath/sdk/impl/authc/OktaAuthNAuthenticator.java

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@
77
import com.stormpath.sdk.application.okta.OktaTokenRequest;
88
import com.stormpath.sdk.authc.AuthenticationResult;
99
import com.stormpath.sdk.authc.AuthenticationResultVisitor;
10+
import com.stormpath.sdk.error.Error;
1011
import com.stormpath.sdk.impl.application.okta.DefaultOktaSigningKeyResolver;
1112
import com.stormpath.sdk.impl.application.okta.OktaSigningKeyResolver;
1213
import com.stormpath.sdk.impl.ds.InternalDataStore;
1314
import com.stormpath.sdk.impl.http.HttpHeaders;
1415
import com.stormpath.sdk.impl.http.MediaType;
1516
import com.stormpath.sdk.lang.Assert;
1617
import com.stormpath.sdk.oauth.AccessTokenResult;
18+
import com.stormpath.sdk.resource.ResourceException;
1719
import io.jsonwebtoken.Claims;
1820
import io.jsonwebtoken.Header;
1921
import io.jsonwebtoken.Jwt;
2022
import io.jsonwebtoken.Jwts;
2123
import io.jsonwebtoken.SigningKeyResolver;
24+
import org.omg.CORBA.DynAnyPackage.Invalid;
2225
import org.slf4j.Logger;
2326
import org.slf4j.LoggerFactory;
2427

@@ -46,17 +49,7 @@ public OktaAuthNAuthenticator(InternalDataStore dataStore) {
4649

4750
public AuthenticationResult authenticate(DefaultUsernamePasswordRequest request) {
4851

49-
// hit the oauth token endpoint
50-
OktaTokenRequest tokenRequest = this.dataStore.instantiate(OktaTokenRequest.class)
51-
.setPassword(new String(request.getCredentials()))
52-
.setUsername(request.getPrincipals())
53-
.setGrantType("password")
54-
.setScope("offline_access");
55-
56-
HttpHeaders httpHeaders = new HttpHeaders();
57-
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
58-
59-
final OktaTokenResponse oktaTokenResponse = this.dataStore.create("/oauth2/v1/token", tokenRequest, OktaTokenResponse.class, httpHeaders);
52+
final OktaTokenResponse oktaTokenResponse = doAuthRequest(request);
6053

6154
// validate the key we just received
6255
SigningKeyResolver keyResolver = dataStore.instantiate(OktaSigningKeyResolver.class);
@@ -88,10 +81,7 @@ public Set<String> getScope() {
8881

8982
@Override
9083
public ApiKey getApiKey() {
91-
return ApiKeys.builder()
92-
.setId("foobar")
93-
.setSecret("barfoo")
94-
.build();
84+
return null;
9585
}
9686

9787
@Override
@@ -111,4 +101,56 @@ public String getHref() {
111101
};
112102
}
113103

104+
private OktaTokenResponse doAuthRequest(DefaultUsernamePasswordRequest request) {
105+
HttpHeaders httpHeaders = new HttpHeaders();
106+
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
107+
108+
// hit the oauth token endpoint
109+
OktaTokenRequest tokenRequest = this.dataStore.instantiate(OktaTokenRequest.class)
110+
.setPassword(new String(request.getCredentials()))
111+
.setUsername(request.getPrincipals())
112+
.setGrantType("password")
113+
.setScope("offline_access");
114+
115+
try {
116+
117+
return this.dataStore.create("/oauth2/v1/token", tokenRequest, OktaTokenResponse.class, httpHeaders);
118+
}
119+
catch (final ResourceException e) {
120+
121+
throw new ResourceException(new Error() {
122+
@Override
123+
public int getStatus() {
124+
return e.getStatus();
125+
}
126+
127+
@Override
128+
public int getCode() {
129+
return 0;
130+
}
131+
132+
@Override
133+
public String getMessage() {
134+
// TODO: i18n, configure error handler for this type of message?
135+
return "Invalid username or password.";
136+
}
137+
138+
@Override
139+
public String getDeveloperMessage() {
140+
return e.getDeveloperMessage();
141+
}
142+
143+
@Override
144+
public String getMoreInfo() {
145+
return e.getMoreInfo();
146+
}
147+
148+
@Override
149+
public String getRequestId() {
150+
return e.getRequestId();
151+
}
152+
});
153+
}
154+
}
155+
114156
}

impl/src/main/java/com/stormpath/sdk/impl/error/OktaError.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.stormpath.sdk.impl.resource.ListProperty;
2222
import com.stormpath.sdk.impl.resource.Property;
2323
import com.stormpath.sdk.impl.resource.StringProperty;
24+
import com.stormpath.sdk.lang.Collections;
2425

2526
import java.io.Serializable;
2627
import java.util.List;
@@ -38,9 +39,10 @@ public class OktaError extends AbstractResource implements Error, Serializable {
3839
static final StringProperty ERROR_SUMMARY = new StringProperty("errorSummary");
3940
static final ListProperty ERROR_CAUSES = new ListProperty("errorCauses");
4041
static final StringProperty ERROR_ID = new StringProperty("errorId");
42+
static final StringProperty ERROR = new StringProperty("error");
4143

4244
private static final Map<String, Property> PROPERTY_DESCRIPTORS = createPropertyDescriptorMap(
43-
STATUS, ERROR_CODE, ERROR_SUMMARY, ERROR_CAUSES, ERROR_ID
45+
STATUS, ERROR_CODE, ERROR_SUMMARY, ERROR_CAUSES, ERROR_ID, ERROR
4446
);
4547

4648
public OktaError(Map<String, Object> body) {
@@ -70,18 +72,21 @@ public int getCode() {
7072
@Override
7173
@SuppressWarnings("unchecked")
7274
public String getMessage() {
73-
List causes = getListProperty(ERROR_CAUSES.getName());
74-
return ((Map<String, String>)causes.get(0)).get("errorSummary");
75+
return getString(ERROR);
7576
}
7677

7778
@Override
7879
public String getDeveloperMessage() {
79-
return "";
80+
return getString(ERROR);
8081
}
8182

8283
@Override
8384
public String getMoreInfo() {
84-
return getString(ERROR_SUMMARY);
85+
List causes = getListProperty(ERROR_CAUSES.getName());
86+
if (!Collections.isEmpty(causes)) {
87+
return ((Map<String, String>) causes.get(0)).get("errorSummary");
88+
}
89+
return getDeveloperMessage();
8590
}
8691

8792
@Override

0 commit comments

Comments
 (0)