Skip to content

Code flow with discovery + hosted login page example#7

Closed
bdemers wants to merge 21 commits intomasterfrom
code-flow
Closed

Code flow with discovery + hosted login page example#7
bdemers wants to merge 21 commits intomasterfrom
code-flow

Conversation

@bdemers
Copy link
Copy Markdown
Contributor

@bdemers bdemers commented Sep 20, 2017

Lots of stuff in here, any feedback is great high level or low.

There are a couple of important changes in this one:
1.) Add call discovery endpoint to simplify spring security oauth config
2.) Support custom 'authorities' claim in ID token
3.) Add support for a customizable hosted login page (using the Okta widget), works like any other Spring redirect.
4.) Renamed the modules, so we can support having a singular Spring Boot Starter for all of your Okta needs (Spring Sec, Spring Sec + Thymeleaf, and non Spring Sec in the future)

Still a bunch of things to do before merging, lots of cleaning (and tests)
But it is at a point where we can chat more about this approach.
Still need to think about how the mvc/thymeleaf module is structured, the current 'optional' dependency is not great
Ran PMD and Findbugs, fixed minor issues
@bdemers bdemers requested review from dogeared and mraible September 20, 2017 19:24
*/
@GetMapping("/")
@PreAuthorize("#oauth2.clientHasRole('Everyone') || #oauth2.hasScope('email')")
// @PreAuthorize("#oauth2.clientHasRole('Everyone') || #oauth2.hasScope('email')")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like delete this line

import java.security.Principal;

@RestController
public class WelcomeResource {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be: WelcomeController or WelcomeResourceController?

return new Welcome("The message of the day is boring.", principal.getName());
}

@XmlRootElement
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ew - why XML? ;)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha! that works for both JSON and XML IIRC, but let me see if that is still needed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm wrong... I swear it was needed at one point...

import java.security.Principal;

@RestController
public class WelcomeResource {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WelcomeResourceController or WelcomeController

oauth2/pom.xml Outdated
<name>Okta Spring Boot :: OAuth2</name>

<properties>
<spring-boot.version>1.5.4.RELEASE</spring-boot.version>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1.5.7 is latest release

import java.util.Map;

@ConfigurationProperties("okta")
public class OktaOAuthProperties {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused on the difference between OkatOAuthProperties and OAuthProperties and why OAuthProperties is embedded in OktaOAuthProperties.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This brings up a few questions, i'm not sure the best way to handle the properties object.
But your point is valid, the top level should be renamed to OktaProperties (on it)

The odd nested OAuthProperties getOauth2()/oauth2 to make Spring's ConfigurationProperties work out of the box.

it might be worth breaking this up into multiple classes, one for each okta.* so one for okta.client, okta.oauth2 and another for okta.web (this last one is already separate)

The okta.client properties are defined by the the SDK's spec so they are reused where possible

}


public OAuthProperties getOauth2() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this should be: getOAuthProperties() or getOAuth2Properties (which also means that the variable should probs be renamed too)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, that might help clear up the confusion (instead of forcing them all in a single class)?

import org.testng.annotations.Test

import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.Matchers.*
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not as critical for tests, but we've had a standard in the past of making imports explicit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, just too many damn static methods in hamcrest, easy enough to clean up the imports though

import org.testng.annotations.Test

import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.Matchers.*
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same note on expanding imports

protected boolean shouldExecute(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) {

if (modelAndView == null || !modelAndView.isReference() /*|| STORMPATH_JSON_VIEW_NAME.equals(modelAndView.getViewName()) */) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time to let go of STORMPATH comments ;)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boo

@bdemers
Copy link
Copy Markdown
Contributor Author

bdemers commented Sep 22, 2017

@dogeared all clear, but, take a look at this comment if you missed it in the scroll back:
https://github.com/okta/okta-spring-security/pull/7/files/fac06be4678b12312f8a730e828335cdd74f4735#r140393885

Thoughts on how these properties should be structured ?

Copy link
Copy Markdown
Contributor

@mraible mraible left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor code formatting comments. Didn't try the examples. Does Travis run integration tests to prove they work?

import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove extra line break.

customLoginRoute: /login

# default is '/login'
redirectUri: /login/okta
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do the defaults need to be changed? Does it work when these aren't specified, or are these settings specific to this example?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I want to pick your brain about this. I'm not super happy with the way this works at the moment. (this is also related to your next comment).
I'm trying to keep the the hosted page stuff optional, and default to a standard redirect (takes less config, easier to debug, etc).

This project still redirects, it just redirects to the oauth2 filter at: /login/okta which grabs the state and then renders the widget template login.html

Longer term it would be nice to handle this all in the same request, and just forward to the login.html template (to save a hop, and configuration)

oauth2:
client:
# Need to figure out how to set this, this needs to be an absolute URI
userAuthorizationUri: http://localhost:8080/login
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a Spring Security setting, or ours?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spring, it needs an absolute URI. (Ideally we need a better solution for this)

</dependencies>

<build>
<defaultGoal>spring-boot:run</defaultGoal>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My fave! I tried to get the Spring Boot guys to do this, but they refused.

}
}


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove extra line break.

protected void init() {

// update properties based on discovery if needed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary line break.

protected void configure(HttpSecurity http) throws Exception {

// FIXME: MVC bleed
http.authorizeRequests().antMatchers("/okta/*.css").permitAll();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spring's fault or ours?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ours, I ran into an ordering issue (?) where a WebSecurityConfigurerAdapter from the thymeleaf module was not getting applied correctly (and blocking the css). A little googling showed that I should apply() other WebSecurityConfigurerAdapter. Thoughts?

return new ResourceServerConfigurerAdapter() {
@Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.resourceId(OAuthProperties.getOauth2().getAudience()); // set audience
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment doesn't match - remove.

@Test
void basicParseTest() {


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too much space.

<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>0.2.0-SNAPSHOT</version>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be ${project.version} to simplify things?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, ${project.version} is not recommended for dependencies. There are cases where if you use a parent from this project in a separately versioned project (other git repo), then then ${project.version} will not resolve correctly. (there is another edge case too, but I forget).

Older versions of the release plugin did update these correctly as well, but that has been fixed.

@bdemers
Copy link
Copy Markdown
Contributor Author

bdemers commented Sep 25, 2017

Thanks for the reviews so far guys! After I get a green merge light I'd like to continue using this as a feature branch and NOT merge to master until the following issues are resolved (hopefully in more targeted PRs):

1.) Extra config when using a hosted login page
2.) Extra redirect when using a hosted login page
3.) Organize the configuration OktaProperties better?
4.) Fix okta.css bleed over in OktaOAuthConfig

If you agree, i'll create issues for each of these and we can merge this to master once they are resolved

Set default Order(80) on OktaHttpSecurityConfigurationAdapter to make one less line of code to explain
@bdemers bdemers changed the title Code flow with discovery & hosted login page Code flow with discovery + hosted login page example Sep 27, 2017
Realize there is too much code here...
@bdemers
Copy link
Copy Markdown
Contributor Author

bdemers commented Sep 28, 2017

Way to much code in here, both for a pull request and in general.
i'm rewriting this in WAY less code, and working better within the bounds of spring boot.
I think i was missing fundamental when i started this PR (and was focused on a hosted page, which is no longer the goal)

@bdemers bdemers closed this Sep 28, 2017
@bdemers bdemers deleted the code-flow branch October 5, 2017 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants