Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added in another module to separate the difference between okta signin widget and truly custom login flow. #35

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions custom-login-authjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Okta Spring Security & Custom Login Page with AuthJs Example

This example shows you how to use the [Okta Spring Boot Library][] to login a user. The login is achieved through the [Authorization Code Flow][] using the [Okta Auth JS Library][], which gives you more control to customize the login experience within your app. After the user authenticates, they are redirected back to the application and a local cookie session is created.


## Prerequisites

Before running this sample, you will need the following:

* An Okta Developer Account, you can sign up for one at https://developer.okta.com/signup/.
* An Okta Application, configured for Web mode. This is done from the Okta Developer Console and you can find instructions [here][OIDC Web Application Setup Instructions]. When following the wizard, use the default properties. They are designed to work with our sample applications.

## Running This Example

There is a pom.xml at the root of this project, that exists to build all of the projects. Each project is independent and could be copied out of this repo as a primer for your own application.

You also need to gather the following information from the Okta Developer Console:

- **Client ID** and **Client Secret** - These can be found on the "General" tab of the Web application that you created earlier in the Okta Developer Console.

- **Issuer** - This is the URL of the authorization server that will perform authentication. All Developer Accounts have a "default" authorization server. The issuer is a combination of your Org URL (found in the upper right of the console home page) and `/oauth2/default`. For example, `https://dev-1234.oktapreview.com/oauth2/default`.

Plug these values into the `mvn` commands used to start the application.

```bash
cd custom-login-authjs
mvn -Dokta.oauth2.issuer=https://{yourOktaDomain}/oauth2/default \
-Dokta.oauth2.clientId={yourClientId} \
-Dokta.oauth2.clientSecret={yourClientSecret} \
-Dokta.client.orgUrl=https://{yourOktaDomain}
```

> **NOTE:** Putting secrets on the command line should ONLY be done for examples, do NOT do this in production. Instead update the projects `application.yml`

Now navigate to http://localhost:8080 in your browser.

If you see a home page that prompts you to login, then things are working! Clicking the **Login** button will render a custom login page, served by the Spring Boot application, that uses the [Okta Auth JS Library][] to perform authentication.

You can login with the same account that you created when signing up for your Developer Org, or you can use a known username and password from your Okta Directory.

> **NOTE:** If you are currently using your Developer Console, you already have a Single Sign-On (SSO) session for your Org. You will be automatically logged into your application as the same user that is using the Developer Console. You may want to use an incognito tab to test the flow from a blank slate.

[Okta Spring Boot Library]: https://github.com/okta/okta-spring-boot
[OIDC Web Application Setup Instructions]: https://developer.okta.com/authentication-guide/implementing-authentication/auth-code#1-setting-up-your-application
[Authorization Code Flow]: https://developer.okta.com/authentication-guide/implementing-authentication/auth-code
[Okta Sign In Widget]: https://github.com/okta/okta-auth-js
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions custom-login/pom.xml → custom-login-authjs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
</parent>

<groupId>com.example.okta</groupId>
<artifactId>okta-spring-boot-oauth-code-flow-custom-login-example</artifactId>
<artifactId>okta-spring-boot-oauth-code-flow-custom-login-authjs-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Okta :: Samples :: Spring Boot :: Code Flow + Custom Login Page</name>
<description>Okta OAuth 2.0 w/ Spring Boot Example + Custom Login Page</description>
<name>Okta :: Samples :: Spring Boot :: Code Flow + Custom Login Page with AuthJs</name>
<description>Okta OAuth 2.0 w/ Spring Boot Example + Custom Login Page with AuthJs</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2017 Okta, 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.okta.spring.example;

import com.okta.spring.config.OktaOAuth2Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;

import javax.servlet.Filter;

/**
* This example renders a custom login page (hosted within this application). You can use a standard login with less
* code (if you don't need to customize the login page) see the 'basic' example at the root of this repository.
*/
@SpringBootApplication
@EnableOAuth2Sso
public class CustomLoginCodeFlowAuthJsExampleApplication {

private final Logger logger = LoggerFactory.getLogger(CustomLoginCodeFlowAuthJsExampleApplication.class);

public static void main(String[] args) {
SpringApplication.run(CustomLoginCodeFlowAuthJsExampleApplication.class, args);
}

/**
* Enable the use of {@link org.springframework.security.access.prepost.PreAuthorize PreAuthorize} annotation
* and OAuth expressions like {code}#oauth2.hasScope('email'){code}.
*/
@EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}

/**
* Create an ApplicationListener that listens for successful logins and simply just logs the principal name.
* @return a new listener
*/
@Bean
protected ApplicationListener<AuthenticationSuccessEvent> authenticationSuccessEventApplicationListener() {
return event -> logger.info("Authentication Success with principal: {}", event.getAuthentication().getPrincipal());
}

@Bean
protected Filter oktaSsoFilter(ApplicationEventPublisher applicationEventPublisher,
OAuth2ClientContext oauth2ClientContext,
AuthorizationCodeResourceDetails authorizationCodeResourceDetails,
ResourceServerTokenServices tokenServices,
OktaOAuth2Properties oktaOAuth2Properties) {

// There are a few package private classes the configure a OAuth2ClientAuthenticationProcessingFilter, in order
// to change how the login redirect works we need to copy a bit of that code here
OAuth2ClientAuthenticationProcessingFilter oktaFilter = new OAuth2ClientAuthenticationProcessingFilter(oktaOAuth2Properties.getRedirectUri());
oktaFilter.setApplicationEventPublisher(applicationEventPublisher);
OAuth2RestTemplate oktaTemplate = new OAuth2RestTemplate(authorizationCodeResourceDetails, oauth2ClientContext);
oktaFilter.setRestTemplate(oktaTemplate);
oktaFilter.setTokenServices(tokenServices);
return oktaFilter;
}

@Configuration
@Order(99) // Must be less then 100 in order to configure before OAuth2SsoDefaultConfiguration
static class OAuth2SecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

private final Filter oktaSsoFilter;

private final OktaOAuth2Properties oktaOAuth2Properties;

OAuth2SecurityConfigurerAdapter(Filter oktaSsoFilter, OktaOAuth2Properties oktaOAuth2Properties) {
this.oktaSsoFilter = oktaSsoFilter;
this.oktaOAuth2Properties = oktaOAuth2Properties;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
// add our SSO Filter in place
.addFilterAfter(oktaSsoFilter, AbstractPreAuthenticatedProcessingFilter.class)
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint(oktaOAuth2Properties.getRedirectUri()))
.accessDeniedHandler((req, res, e) -> res.sendRedirect("/403"))

// allow anonymous users to access the root page
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/css/**").permitAll()
.antMatchers("/**").authenticated()

// send the user back to the root page when they logout
.and()
.logout().logoutSuccessUrl("/");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.okta.spring.example.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.security.Principal;

@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "home";
}
}
70 changes: 70 additions & 0 deletions custom-login-authjs/src/main/resources/templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!--
~ Copyright 2017 Okta, 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.
-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
<!--/*/ <th:block th:include="head :: head"/> /*/-->

<link href="/css/okta.css" rel="stylesheet" type="text/css"/>

<script src="https://ok1static.oktacdn.com/assets/js/sdk/okta-auth-js/1.6.0/okta-auth-js.min.js" type="text/javascript"></script>
</head>
<body class="login">

<div class="container">
<h2>Login</h2>
<form class="form-inline">
<label class="sr-only" for="email">Email</label>
<input type="text" class="form-control mb-2 mr-sm-2" id="email" placeholder="email">

<label class="sr-only" for="email">Password</label>
<input type="password" class="form-control mb-2 mr-sm-2" id="password" placeholder="password">

<button type="submit" onclick="doIt(); return false;" class="btn btn-primary mb-2">Submit</button>
</form>
</div>

<script th:inline="javascript">
/*<![CDATA[*/

var authClient = new OktaAuth({
url: /*[[${oktaBaseUrl}]]*/ 'https://{yourOktaDomain}',
clientId: /*[[${oktaClientId}]]*/ '{oktaClientId}',
redirectUri: /*[[${redirectUri}]]*/ '{redirectUri}',
issuer: /*[[${issuerUri}]]*/ '{issuerUri}'
});

function doIt() {
authClient.signIn({
username: $('#email').val(),
password: $('#password').val()
})
.then(function (transaction) {
if (transaction.status === 'SUCCESS') {
authClient.token.getWithRedirect({
responseType: 'code',
state: /*[[${state}]]*/ '{state}' || false,
scopes: /*[[${scopes}]]*/ '[scopes]',
sessionToken: transaction.sessionToken
});
}
});
}

/*]]>*/
</script>
</body>
</html>
4 changes: 2 additions & 2 deletions custom-login/README.md → custom-login-osw/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Okta Spring Security & Custom Login Page Example
# Okta Spring Security & Custom Login Page with SignIn Widget Example

This example shows you how to use the [Okta Spring Boot Library][] to login a user. The login is achieved through the [Authorization Code Flow][] using the [Okta Sign In Widget][], which gives you more control to customize the login experience within your app. After the user authenticates, they are redirected back to the application and a local cookie session is created.

Expand All @@ -23,7 +23,7 @@ You also need to gather the following information from the Okta Developer Consol
Plug these values into the `mvn` commands used to start the application.

```bash
cd custom-login
cd custom-login-osw
mvn -Dokta.oauth2.issuer=https://{yourOktaDomain}/oauth2/default \
-Dokta.oauth2.clientId={yourClientId} \
-Dokta.oauth2.clientSecret={yourClientSecret} \
Expand Down
Loading