Skip to content

Commit

Permalink
feat: Introduce basic authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
sumanmaity1234 committed Feb 17, 2022
1 parent 4f6d6ae commit abfdeab
Show file tree
Hide file tree
Showing 16 changed files with 553 additions and 92 deletions.
18 changes: 12 additions & 6 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
fileignoreconfig:
- filename: .github/workflows/checks.yml
checksum: 365a1d2aa78bafe126342b8e01dc9271b065121e5c655ce9a03820d986a960ea
- filename: .github/workflows/build.yml
checksum: 22fbbc7d3839fd65cdeb73d71c52006fadadfeb5d3cbdac7bae5d9795f20edf8
- filename: .github/workflows/checks.yml
checksum: 365a1d2aa78bafe126342b8e01dc9271b065121e5c655ce9a03820d986a960ea
- filename: backend/gradle/config/checkstyle.xml
checksum: 42bddec292c1e767c376d9a2344581a901ce9bc538950a6402b02d71c7e445a1
- filename: backend/src/main/java/de/otto/platform/gitactionboard/adapters/controller/AuthenticationController.java
checksum: 51c5a4ce0402fe4550c90468b22a9007a643714573eba99d611a3d2ad3012f09
- filename: backend/src/main/java/de/otto/platform/gitactionboard/adapters/controller/BasicAuthenticationController.java
checksum: a34c899d5594d66729c93f0ee7a74bd995c5522790ca7110baeebe3e0565ffd3
- filename: backend/src/main/java/de/otto/platform/gitactionboard/adapters/service/job/GithubJobDetailsService.java
checksum: 04a9aaea483e1398231870d300a7d2be802e80d4b2db8e1e4568aa1165675ddb
- filename: backend/src/main/resources/application.properties
checksum: a8e9a356bb11b97e2229340e5339a7e0105ecd51dc79bc8165d59ed95705ae3a
- filename: backend/src/test/resources/.htpasswd
checksum: 2e31e64b696f0f9267a4ebd694d90b27c6e0c4cefdd11349d199e185daab2d6c
- filename: bin/install-talisman.sh
checksum: 94703e38e7c00dbac423eaf0a25709dd83d8cd1274fb7d31628f4aabc60e287b
- filename: doc/sample1.png
checksum: 47c2e47c03ac67b606cc987d409e2d6f22aea3c2ab3ae9adb95abad6d607b711
- filename: doc/sample2.png
checksum: 4b7ffe6db1c4f23e3dfa9c52fa15699f5e3d8d13bc9b45d5f137c2706e3edd7d
- filename: frontend/src/components/Jobs.vue
checksum: c9c38b10e4eca52659618f21d7f382dc97ec853f3c0fd750ce021edfbe9db27b
- filename: frontend/package-lock.json
checksum: 64af277761f9b9e5fea499ba2818595033b4c4b1d26c1875c98d4809a2c937fd
- filename: frontend/src/components/Job.vue
checksum: f50c9eeecc39b443e2411cee7e355ea4f8f1d3e579558f3d478dd97a45a2c346
- filename: backend/src/main/java/de/otto/platform/gitactionboard/adapters/service/job/GithubJobDetailsService.java
checksum: 04a9aaea483e1398231870d300a7d2be802e80d4b2db8e1e4568aa1165675ddb
- filename: frontend/src/components/Jobs.vue
checksum: c9c38b10e4eca52659618f21d7f382dc97ec853f3c0fd750ce021edfbe9db27b
version: "1.0"
1 change: 1 addition & 0 deletions backend/gradle/jacoco.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ jacoco {

def excludes = [
"de/otto/platform/gitactionboard/config/WebSecurityConfig.class",
"de/otto/platform/gitactionboard/config/WebSecurityConfig\$*.class",
"de/otto/platform/gitactionboard/config/NoOpsWebSecurityConfig.class",
]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package de.otto.platform.gitactionboard.adapters.controller;

import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class AuthenticationController {
private final boolean isBasicAuthEnabled;
private final boolean isOauth2Enabled;

public AuthenticationController(
@Value("${BASIC_AUTH_USER_DETAILS_FILE_PATH:}") String basicAuthDetailsFilePath,
@Value("${spring.security.oauth2.client.registration.github.client-id:-}")
String githubClientId) {
this.isBasicAuthEnabled = StringUtils.hasText(basicAuthDetailsFilePath);
this.isOauth2Enabled = !"-".equals(githubClientId);
}

@GetMapping(path = "/available-auths")
public List<AuthenticationMechanism> getAvailableAuthMechanism() {
final ArrayList<AuthenticationMechanism> authenticationMechanisms = new ArrayList<>();

if (isBasicAuthEnabled) authenticationMechanisms.add(AuthenticationMechanism.BASIC_AUTH);
if (isOauth2Enabled) authenticationMechanisms.add(AuthenticationMechanism.OAUTH2);

return authenticationMechanisms;
}

public enum AuthenticationMechanism {
OAUTH2,
BASIC_AUTH
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package de.otto.platform.gitactionboard.adapters.controller;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.net.URLEncoder;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@ConditionalOnExpression(
"T(org.springframework.util.StringUtils).hasText('${BASIC_AUTH_USER_DETAILS_FILE_PATH:}')")
public class BasicAuthenticationController {
private static final String NAME = "name";
private static final String USERNAME = "username";
private static final String ACCESS_TOKEN = "access_token";

private static final int ONE_DAY = 60 * 60 * 24;

private final AuthenticationManager authenticationManager;

public BasicAuthenticationController(
@Qualifier("basicAuthenticationManager") AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}

@PostMapping(path = "/login/basic")
public ResponseEntity<Object> login(
@RequestBody AuthRequest authRequest, HttpServletResponse response) {
final String username = authRequest.getUsername();
final String password = authRequest.getPassword();
try {
final Authentication authentication =
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password));

if (authentication.isAuthenticated()) {
response.addCookie(createCookie(NAME, username, ONE_DAY));
response.addCookie(createCookie(USERNAME, username, ONE_DAY));
response.addCookie(
createCookie(ACCESS_TOKEN, createAccessToken(username, password), ONE_DAY));
return ResponseEntity.ok().build();
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
} catch (BadCredentialsException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}

private String createAccessToken(String username, String password) {
final byte[] encodedAuth =
Base64.encodeBase64(String.format("%s:%s", username, password).getBytes(UTF_8));
return String.format("Basic %s", new String(encodedAuth, UTF_8));
}

private Cookie createCookie(String cookieName, String value, int maxAge) {
final Cookie cookie = new Cookie(cookieName, URLEncoder.encode(value, UTF_8));
cookie.setMaxAge(maxAge);
cookie.setPath("/");
return cookie;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
static class AuthRequest {
private String username;
private String password;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.otto.platform.gitactionboard.adapters.controller;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

import de.otto.platform.gitactionboard.adapters.service.cruisecontrol.CruiseControlService;
import de.otto.platform.gitactionboard.adapters.service.cruisecontrol.Project;
Expand All @@ -17,8 +18,8 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -34,7 +35,7 @@ public class GithubController {
@Cacheable(cacheNames = "cctrayXml", sync = true)
@GetMapping(value = "/cctray.xml", produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<String> getCctrayXml(
@CookieValue(value = "access_token", required = false) String accessToken) {
@RequestHeader(value = AUTHORIZATION, required = false) String accessToken) {
return createResponseEntityBodyBuilder()
.body(cruiseControlService.convertToXml(fetchJobs(accessToken)));
}
Expand All @@ -56,7 +57,7 @@ private String decode(String urlEncodedValue) {
@Cacheable(cacheNames = "cctray", sync = true)
@GetMapping(value = "/cctray", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<Project>> getCctray(
@CookieValue(value = "access_token", required = false) String accessToken) {
@RequestHeader(value = AUTHORIZATION, required = false) String accessToken) {
return createResponseEntityBodyBuilder()
.body(cruiseControlService.convertToJson(fetchJobs(accessToken)));
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.otto.platform.gitactionboard.config.security;

import org.springframework.boot.autoconfigure.condition.AllNestedConditions;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

public class DisableAuthentication extends AllNestedConditions {
public DisableAuthentication() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}

@ConditionalOnProperty(
name = "spring.security.oauth2.client.registration.github.client-id",
havingValue = "-",
matchIfMissing = true)
static class GithubAuthConfigMissing {}

@ConditionalOnExpression(
"!T(org.springframework.util.StringUtils).hasText('${BASIC_AUTH_USER_DETAILS_FILE_PATH:}')")
static class BasicAuthConfigMissing {}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.otto.platform.gitactionboard.config;
package de.otto.platform.gitactionboard.config.security;

import static java.nio.charset.StandardCharsets.UTF_8;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package de.otto.platform.gitactionboard.config;
package de.otto.platform.gitactionboard.config.security;

import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
@ConditionalOnProperty(
name = "spring.security.oauth2.client.registration.github.client-id",
havingValue = "-",
matchIfMissing = true)
@Conditional(DisableAuthentication.class)
@Slf4j
public class NoOpsWebSecurityConfig extends WebSecurityConfigurerAdapter {

Expand Down
Loading

0 comments on commit abfdeab

Please sign in to comment.