├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── backend
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── pl
│ │ └── bmstefanski
│ │ └── website
│ │ ├── WebConfiguration.java
│ │ ├── WebsiteApplication.java
│ │ └── auth
│ │ ├── SessionController.java
│ │ └── SpringSecurityConfiguration.java
│ └── resources
│ ├── application.yml
│ ├── banner.txt
│ └── log4j2.xml
├── external
├── home.png
├── login.png
└── not-logged-in.png
└── frontend
├── .gitignore
├── README.md
├── babel.config.js
├── config.json
├── package.json
├── public
├── favicon.ico
├── fonts
│ ├── FontAwesome.otf
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.svg
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
└── index.html
└── src
├── App.vue
├── assets
└── logo.png
├── components
├── auth
│ ├── LoginComponent.vue
│ └── LogoutComponent.vue
└── home
│ └── HomeComponent.vue
├── main.js
├── router
├── index.js
└── routes.js
└── store
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Maven ###
2 | target/
3 | pom.xml.tag
4 | pom.xml.releaseBackup
5 | pom.xml.versionsBackup
6 | pom.xml.next
7 | release.properties
8 | dependency-reduced-pom.xml
9 | buildNumber.properties
10 | .mvn/timing.properties
11 |
12 | ### Intellij ###
13 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
14 |
15 | ## Directory-based project format:
16 | .idea/
17 | *.css.map
18 |
19 | ## File-based project format:
20 | *.ipr
21 | *.iws
22 | *.iml
23 | *.log
24 |
25 | ## Plugin-specific files:
26 |
27 | # IntelliJ
28 | /out/
29 | /bin/
30 | /notes
31 |
32 | # mpeltonen/sbt-idea plugin
33 | .idea_modules/
34 |
35 | # JIRA plugin
36 | atlassian-ide-plugin.xml
37 |
38 | # Crashlytics plugin (for Android Studio and IntelliJ)
39 | com_crashlytics_export_strings.xml
40 | crashlytics.properties
41 | crashlytics-build.properties
42 |
43 | ### Eclipse ###
44 | *.pydevproject
45 | .metadata
46 | .gradle
47 | bin/
48 | tmp/
49 | *.tmp
50 | *.bak
51 | *.swp
52 | *~.nib
53 | local.properties
54 | .settings/
55 | .loadpath
56 |
57 | # Eclipse Core
58 | .project
59 |
60 | # External tool builders
61 | .externalToolBuilders/
62 |
63 | # Locally stored "Eclipse launch configurations"
64 | *.launch
65 |
66 | # CDT-specific
67 | .cproject
68 |
69 | # JDT-specific (Eclipse Java Development Tools)
70 | .classpath
71 |
72 | # Java annotation processor (APT)
73 | .factorypath
74 |
75 | # PDT-specific
76 | .buildpath
77 |
78 | # sbteclipse plugin
79 | .target
80 |
81 | # TeXlipse plugin
82 | .texlipse
83 |
84 | ### Java ###
85 | *.class
86 |
87 | # Mobile Tools for Java (J2ME)
88 | .mtj.tmp/
89 |
90 | # Package Files #
91 | *.war
92 | *.ear
93 |
94 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
95 | hs_err_pid*
96 |
97 | # Vue & NodeJS
98 | .DS_Store
99 | node_modules/
100 | dist/
101 | npm-debug.log*
102 | yarn-debug.log*
103 | yarn-error.log*
104 | /test/e2e/reports
105 | selenium-debug.log
106 | package-lock.json
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | dist: trusty
3 | sudo: false
4 |
5 | os:
6 | - linux
7 | - osx
8 |
9 | jdk:
10 | - openjdk9
11 | - openjdk10
12 |
13 | matrix:
14 | fast_finish: true
15 | include:
16 | - os: linux
17 | jdk: openjdk8
18 | allow_failures:
19 | - jdk: openjdk11
20 | - jdk: openjdk-ea
21 | - jdk: oraclejdk-ea
22 |
23 | before_install:
24 | - unset _JAVA_OPTIONS
25 |
26 | script:
27 | - cd backend
28 | - mvn clean install spring-boot:repackage
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Bartłomiej Stefański
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spring Web Oauth Example [](https://travis-ci.com/bmstefanski/spring-vue-rest-oauth2)
2 | Example website with OAuth authentication made by using Spring Boot
3 |
--------------------------------------------------------------------------------
/backend/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | pl.bmstefanski
8 | website
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | website
13 | Demo project for Spring Boot
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 2.1.1.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-security
36 |
37 |
38 | org.springframework.security.oauth
39 | spring-security-oauth2
40 | 2.3.4.RELEASE
41 |
42 |
43 | org.springframework.security.oauth.boot
44 | spring-security-oauth2-autoconfigure
45 | 2.1.1.RELEASE
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/backend/src/main/java/pl/bmstefanski/website/WebConfiguration.java:
--------------------------------------------------------------------------------
1 | package pl.bmstefanski.website;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.web.servlet.config.annotation.CorsRegistry;
5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
6 |
7 | @Configuration
8 | public class WebConfiguration implements WebMvcConfigurer {
9 |
10 | @Override
11 | public void addCorsMappings(CorsRegistry registry) {
12 | registry.addMapping("/**")
13 | .allowedOrigins("http://localhost:8080")
14 | .allowedMethods("GET", "POST", "HEAD", "OPTIONS", "PUT", "PATCH", "DELETE")
15 | .allowCredentials(true);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/backend/src/main/java/pl/bmstefanski/website/WebsiteApplication.java:
--------------------------------------------------------------------------------
1 | package pl.bmstefanski.website;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class WebsiteApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(WebsiteApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/backend/src/main/java/pl/bmstefanski/website/auth/SessionController.java:
--------------------------------------------------------------------------------
1 | package pl.bmstefanski.website.auth;
2 |
3 | import java.io.IOException;
4 | import java.security.Principal;
5 | import java.util.Collections;
6 | import javax.servlet.http.HttpServletResponse;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.ResponseEntity;
9 | import org.springframework.web.bind.annotation.GetMapping;
10 | import org.springframework.web.bind.annotation.RestController;
11 |
12 | @RestController
13 | public class SessionController {
14 |
15 | @GetMapping("sessions/me")
16 | public ResponseEntity> user(Principal principal) {
17 | if (principal == null) {
18 | return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Collections.singletonMap("error", "unauthorized"));
19 | // dat not me!!!!!!! TODO should be custom exception handler
20 | }
21 |
22 | return ResponseEntity.ok(principal);
23 | }
24 |
25 | @GetMapping("sessions/github/callback")
26 | public void githubCallback(HttpServletResponse response) throws IOException {
27 | response.sendRedirect("http://localhost:8080/#/");
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/backend/src/main/java/pl/bmstefanski/website/auth/SpringSecurityConfiguration.java:
--------------------------------------------------------------------------------
1 | package pl.bmstefanski.website.auth;
2 |
3 | import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 |
8 | @Configuration
9 | @EnableOAuth2Sso
10 | public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
11 |
12 | @Override
13 | protected void configure(HttpSecurity http) throws Exception {
14 | http
15 | .httpBasic().disable()
16 | .antMatcher("/**").authorizeRequests()
17 | .antMatchers("/sessions/github/callback").authenticated()
18 | .anyRequest().permitAll();
19 | }
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/backend/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 3000
3 | servlet:
4 | session:
5 | cookie:
6 | name: backend-session
7 | security:
8 | oauth2:
9 | sso:
10 | login-path: /sessions/github
11 | client:
12 | client-id: clientid
13 | client-secret: clientsecret
14 | access-token-uri: https://github.com/login/oauth/access_token
15 | user-authorization-uri: https://github.com/login/oauth/authorize
16 | token-name: oauth_token
17 | authentication-scheme: query
18 | client-authentication-scheme: form
19 | scope: user
20 | resource:
21 | prefer-token-info: false
22 | user-info-uri: https://api.github.com/user
23 |
24 |
--------------------------------------------------------------------------------
/backend/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ▀████ ▐████▀ ████████▄
2 | ███▌ ████▀ ███ ▀███
3 | ███ ▐███ ███ ███
4 | ▀███▄███▀ ███ ███
5 | ████▀██▄ ███ ███
6 | ▐███ ▀███ ███ ███
7 | ▄███ ███▄ ███ ▄███
8 | ████ ███▄ ████████▀
9 |
10 | ${AnsiColor.BLACK}█${AnsiColor.GREEN}█${AnsiColor.BLUE}█${AnsiColor.BRIGHT_BLACK}█${AnsiColor.BRIGHT_CYAN}█${AnsiColor.BRIGHT_GREEN}█${AnsiColor.BRIGHT_MAGENTA}█${AnsiColor.BRIGHT_RED}█${AnsiColor.BRIGHT_WHITE}█${AnsiColor.BRIGHT_YELLOW}█${AnsiColor.CYAN}█${AnsiColor.MAGENTA}█${AnsiColor.RED}█${AnsiColor.WHITE}█${AnsiColor.YELLOW}█
11 | ${AnsiColor.GREEN}:: Spring Boot :: ${AnsiColor.BLACK} Running ${spring-boot.version}
12 |
--------------------------------------------------------------------------------
/backend/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/external/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/external/home.png
--------------------------------------------------------------------------------
/external/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/external/login.png
--------------------------------------------------------------------------------
/external/not-logged-in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/external/not-logged-in.png
--------------------------------------------------------------------------------
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/frontend/README.md:
--------------------------------------------------------------------------------
1 | # frontend
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your tests
19 | ```
20 | npm run test
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/frontend/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "API_URL": "http://localhost:3000"
3 | }
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "nodemon ./node_modules/@vue/cli-service/bin/vue-cli-service.js serve",
7 | "serve": "vue-cli-service serve",
8 | "build": "vue-cli-service build",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "nodemon": "^1.18.6",
13 | "vue": "^2.5.17",
14 | "vue-router": "^3.0.1",
15 | "vuex": "^3.0.1"
16 | },
17 | "devDependencies": {
18 | "@vue/cli-plugin-babel": "^3.1.1",
19 | "@vue/cli-plugin-eslint": "^3.1.5",
20 | "@vue/cli-service": "^3.1.4",
21 | "babel-eslint": "^10.0.1",
22 | "eslint": "^5.8.0",
23 | "eslint-plugin-vue": "^5.0.0-0",
24 | "vue-template-compiler": "^2.5.17"
25 | },
26 | "eslintConfig": {
27 | "root": true,
28 | "env": {
29 | "node": true
30 | },
31 | "extends": [
32 | "plugin:vue/essential",
33 | "eslint:recommended"
34 | ],
35 | "rules": {},
36 | "parserOptions": {
37 | "parser": "babel-eslint"
38 | }
39 | },
40 | "postcss": {
41 | "plugins": {
42 | "autoprefixer": {}
43 | }
44 | },
45 | "browserslist": [
46 | "> 1%",
47 | "last 2 versions",
48 | "not ie <= 8"
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/frontend/public/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/public/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/frontend/public/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/public/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/frontend/public/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/public/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/frontend/public/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/public/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/frontend/public/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/public/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Spring Vue Rest OAuth2
11 |
12 | Home
13 |
15 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/frontend/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/frontend/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bmstefanski/spring-vue-rest-oauth2/de67c2dd8f85baed2698e40a0d537dccdba5b84e/frontend/src/assets/logo.png
--------------------------------------------------------------------------------
/frontend/src/components/auth/LoginComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sign in with Github
4 |
5 |
6 |
7 |
18 |
19 |
113 |
114 |
--------------------------------------------------------------------------------
/frontend/src/components/auth/LogoutComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
--------------------------------------------------------------------------------
/frontend/src/components/home/HomeComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Welcome
4 | You are not logged in!
5 |
6 |
7 |
8 |
25 |
--------------------------------------------------------------------------------
/frontend/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App";
3 | import router from "./router";
4 | import store from './store';
5 |
6 | new Vue({
7 | store,
8 | router: router,
9 | render: h => h(App)
10 | }).$mount('#app');
--------------------------------------------------------------------------------
/frontend/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 | import {routes} from "./routes";
4 |
5 | Vue.use(VueRouter);
6 |
7 | const router = new VueRouter({
8 | routes: routes
9 | });
10 |
11 | router.beforeEach((to, from, next) => {
12 | let requiresAuth = to.matched.some(value => value.meta.requiresAuth);
13 | let currentUser = localStorage.getItem("currentUser");
14 |
15 | if (requiresAuth && !currentUser || requiresAuth && currentUser === {}) {
16 | next("/login");
17 | } else {
18 | next();
19 | }
20 |
21 | });
22 |
23 | export default router;
--------------------------------------------------------------------------------
/frontend/src/router/routes.js:
--------------------------------------------------------------------------------
1 | import HomeComponent from "../components/home/HomeComponent";
2 | import LoginComponent from "../components/auth/LoginComponent";
3 | import LogoutComponent from "../components/auth/LogoutComponent";
4 |
5 | export const routes = [{
6 | path: '/',
7 | name: 'Home',
8 | component: HomeComponent,
9 | meta: {
10 | requiresAuth: false
11 | }
12 | },
13 | {
14 | path: '/login',
15 | name: 'Login',
16 | component: LoginComponent,
17 | meta: {
18 | requiresAuth: false
19 | }
20 | },
21 | {
22 | path: '/logout',
23 | name: "Logout",
24 | component: LogoutComponent,
25 | meta: {
26 | requiresAuth: true
27 | }
28 | }
29 | ];
--------------------------------------------------------------------------------
/frontend/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 | import axios from "axios";
4 |
5 | Vue.use(Vuex);
6 |
7 | const SET_USER = "SET_USER";
8 |
9 | export default new Vuex.Store({
10 | state: {
11 | currentUser: JSON.parse(localStorage.getItem("currentUser")) || {},
12 | },
13 | mutations: {
14 | [SET_USER](state, payload) {
15 | state.currentUser = payload;
16 | }
17 | },
18 | actions: {
19 | fetchUser({commit}) {
20 | axios.get("http://localhost:3000/sessions/me", {withCredentials: true}).then(response => {
21 | commit(SET_USER, response.data);
22 | localStorage.setItem("currentUser", JSON.stringify(this.state.currentUser));
23 | }).catch(() => {
24 | commit(SET_USER, {});
25 | });
26 | },
27 | logout({commit}) {
28 | commit(SET_USER, {});
29 | localStorage.setItem("currentUser", {});
30 | document.cookie = "backend-session" + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
31 | }
32 | },
33 | getters: {
34 | isAuthenticated: (state) => {
35 | return state.currentUser.toString().includes("name");
36 | }
37 | }
38 | })
--------------------------------------------------------------------------------