Permalink
Browse files

Implemented spring boot app

  • Loading branch information...
cternes committed Mar 17, 2016
1 parent 1c8de81 commit 19ef08bba77b3c459a8113a4ada29142e7b2d3f8
@@ -0,0 +1,12 @@
package de.slackspace.keycloaktutorial;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class KeyCloakTutorial {
public static void main(String[] args) {
SpringApplication.run(KeyCloakTutorial.class, args);
}
}
@@ -0,0 +1,19 @@
package de.slackspace.keycloaktutorial.contract.domain;
public class Contract {
private String name;
public Contract(String name) {
this.setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,36 @@
package de.slackspace.keycloaktutorial.contract.web;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import de.slackspace.keycloaktutorial.contract.domain.Contract;
import de.slackspace.keycloaktutorial.security.domain.CurrentUser;
import de.slackspace.keycloaktutorial.security.domain.UserDetails;
@RestController
@RequestMapping(value = "/api/contracts")
public class ContractResource {
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public List<Contract> getContracts(@CurrentUser UserDetails userDetails) {
Contract a = new Contract("a - called by user: " + createUserAppendix(userDetails));
Contract b = new Contract("b - called by user: " + createUserAppendix(userDetails));
List<Contract> contracts = new ArrayList<>();
contracts.add(a);
contracts.add(b);
return contracts;
}
private String createUserAppendix(UserDetails userDetails) {
return userDetails.getFullName() + " (id= " + userDetails.getId() + ")";
}
}
@@ -0,0 +1,12 @@
package de.slackspace.keycloaktutorial.security.domain;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {}
@@ -0,0 +1,48 @@
package de.slackspace.keycloaktutorial.security.domain;
import java.util.Set;
public class UserDetails {
private String id;
private String email;
private String firstName;
private String lastName;
private Set<String> roles;
public UserDetails(String id, String firstName, String lastName, String email, Set<String> roles) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.roles = roles;
}
public String getEmail() {
return email;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Set<String> getRoles() {
return roles;
}
public String getFullName() {
return getFirstName() + " " + getLastName();
}
public String getId() {
return id;
}
}
@@ -0,0 +1,24 @@
package de.slackspace.keycloaktutorial.security.web.config;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import de.slackspace.keycloaktutorial.security.web.resolver.UserDetailsArgumentResolver;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(createUserDetailsResolver());
}
@Bean
public UserDetailsArgumentResolver createUserDetailsResolver() {
return new UserDetailsArgumentResolver();
}
}
@@ -0,0 +1,47 @@
package de.slackspace.keycloaktutorial.security.web.resolver;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
import org.keycloak.representations.AccessToken;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import de.slackspace.keycloaktutorial.security.domain.CurrentUser;
import de.slackspace.keycloaktutorial.security.domain.UserDetails;
public class UserDetailsArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
if (supportsParameter(methodParameter)) {
return createUserDetails(webRequest);
}
else {
return WebArgumentResolver.UNRESOLVED;
}
}
@SuppressWarnings("unchecked")
private Object createUserDetails(NativeWebRequest webRequest) {
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal =
(KeycloakPrincipal<RefreshableKeycloakSecurityContext>) webRequest.getUserPrincipal();
AccessToken token = principal.getKeycloakSecurityContext().getToken();
return new UserDetails(token.getId(), token.getGivenName(), token.getFamilyName(), token.getEmail(),
token.getRealmAccess().getRoles());
}
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.getParameterAnnotation(CurrentUser.class) != null
&& methodParameter.getParameterType().equals(UserDetails.class);
}
}
@@ -0,0 +1,14 @@
server.port = 8000
keycloak.realm = Demo-Realm
keycloak.realmKey = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkRS35Z5lblNpvfHr8C6XEGi9vwYew737+LmcpDbxamLVSdNEWi01Gh2TXCWjDsONaUmvQBIVPvJM5dRmnR5lNtYFnRr6vrT/18I/+E/pU/5a9fj0hMyib1HEsKslI6P2os1vunIiHgkDJkePo9tTbRsG71WH7fXM7BSienZO0ZLV1TbgiLj+PSoFLzAHF0P3BXzHIGTqHzs/UHZ/7ub9Oc2vpSXi4IZKGVLQnc9VNZaMu0QWgnqjMCr7CQRORMQ+y4QGw+DFaZ1pBNpZ+bgy6wKSf17U/5Va/CWs/+UjGj50L/1QqertuMcFKqnnQDLhRmnQErLtdpXzop0YQxka/QIDAQAB
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.ssl-required = external
keycloak.resource = tutorial-backend
keycloak.bearer-only = true
keycloak.credentials.secret = 44c91fb2-d789-42ae-aa0b-d14a10fb1383
keycloak.securityConstraints[0].securityCollections[0].name = spring secured api
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
keycloak.securityConstraints[0].securityCollections[0].authRoles[1] = manager
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api/*
@@ -0,0 +1,13 @@
<configuration debug="false">
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.springframework.security" level="DEBUG" />
<logger name="org.springframework.web.filter" level="DEBUG" />
<logger name="org.keycloak" level="DEBUG" />
<root level="INFO">
<appender-ref ref="stdout" />
</root>
</configuration>

0 comments on commit 19ef08b

Please sign in to comment.