Is it possible to store tokens for example in Redis when use spring-authorization-server. In spring-security-oauth we can define TokenStore:
#Bean
public TokenStore redisTokenStore() {
RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
redisTokenStore.setPrefix(redisTokenPrefix);
return redisTokenStore;
}
In theory, i can implement interface OAuth2AuthorizationService but maybe there is an easier and more beautiful solution
Implementing OAuth2AuthorizationService is the correct way to do this. There is no built-in support for an integration with Redis. See #558 for more info.
Related
In spring-amqp 2.0.3.RELEASE module it's no possible to use custom MessagingMessageListenerAdapter in SimpleMessageListenerContainerFactory.
Even thought registration own bean we stuck at highest one, where last object instance just hard created thought "new MethodRabbitListenerEndpoint" at org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor#processAmqpListener.
Maybe spring developers could add some producer registration to SimpleMessageListenerContainerFactory like "smlcf.setMessageListenerAdapterCreator"
I think what you are asking can be done via a RabbitListenerAnnotationBeanPostProcessor extension:
#Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
#Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static RabbitListenerAnnotationBeanPostProcessor myRabbitListenerAnnotationBeanPostProcessor() {
return new RabbitListenerAnnotationBeanPostProcessor() {
#Override
protected void processListener(MethodRabbitListenerEndpoint endpoint, RabbitListener rabbitListener, Object bean,
Object adminTarget, String beanName) {
super.processListener(new MyMethodRabbitListenerEndpoint(), rabbitListener, proxy, adminTarget, beanName);
}
};
}
But what you are saying about retry for the reply really makes sense and we definitely should consider to let to inject a RabbitTemplate into the RabbitListenerContainerFactory.
Feel free to raise a JIRA on the matter.
I have created a story for adding retry functionality for ReplyTo https://jira.spring.io/browse/AMQP-825
Can you explain where the advice handling #PreAuthorize("hasRole('ADMIN')") retrieves the SecurityContext in a Reactive application?
The following Spring Security example is a good illustration of this kind of usage: https://github.com/spring-projects/spring-security/tree/5.0.0.M4/samples/javaconfig/hellowebflux-method
After checking the Spring Security Webflux source code, I've found some implementations of SecurityContextRepository but the load method needs the ServerWebExchange as a parameter.
I'm trying to understand how to replace SecurityContextHolder.getContext().getAuthentication() call in a standard service (because ThreadLocal is no longer an option in a Reactive Application), but I don't understand how to replace this with a call to a SecurityContextRepository without a reference on the ServerWebExchange.
The ReactiveSecurityContextHolder provides the authentication in a reactive way, and is analogous to SecurityContextHolder.
Its getContext() method provides a Mono<SecurityContext>, just like SecurityContextHolder.getContext() provides a SecurityContext.
ReactiveSecurityContextHolder
.getContext()
.map(context ->
context.getAuthentication()
You're right, ThreadLocal is no longer an option because the processing of a request is not tied to a particular thread.
Currently, Spring Security is storing the authentication information as a ServerWebExchange attribute, so tied to the current request/response pair. But you still need that information when you don't have direct access to the current exchange, like #PreAuthorize.
The authentication information is stored in the Reactive pipeline itself (so accessible from your Mono or Flux), which is a very interesting Reactor feature - managing a context tied to a particular Subscriber (in a web application, the HTTP client is pulling data from the server and acts as such).
I'm not aware of an equivalent of SecurityContextHolder, or some shortcut method to get the Authentication information from the context.
See more about Reactor Context feature in the reference documentation.
You can also see an example of that being used in Spring Security here.
I implemented a JwtAuthenticationConverter (kotlin):
#Component
class JwtAuthenticationConverter : Function<ServerWebExchange,
Mono<Authentication>> {
#Autowired
lateinit var jwtTokenUtil: JwtTokenUtil
#Autowired
lateinit var userDetailsService: ReactiveUserDetailsService
private val log = LogFactory.getLog(this::class.java)
override fun apply(exchange: ServerWebExchange): Mono<Authentication> {
val request = exchange.request
val token = getJwtFromRequest(request)
if ( token != null )
try {
return userDetailsService.findByUsername(jwtTokenUtil.getUsernameFromToken(token))
.map { UsernamePasswordAuthenticationToken(it, null, it.authorities) }
} catch ( e: Exception ) {
exchange.response.statusCode = HttpStatus.UNAUTHORIZED
exchange.response.headers["internal-message"] = e.message
log.error(e)
}
return Mono.empty()
}
private fun getJwtFromRequest(request: ServerHttpRequest): String? {
val bearerToken = request.headers[SecurityConstants.TOKEN_HEADER]?.first {
it.startsWith(SecurityConstants.TOKEN_PREFIX, true)}
return if (bearerToken.isNullOrBlank()) null else bearerToken?.substring(7, bearerToken.length)
}
And then I set a SecurityConfig like this:
val authFilter = AuthenticationWebFilter(ReactiveAuthenticationManager {
authentication: Authentication -> Mono.just(authentication)
})
authFilter.setAuthenticationConverter(jwtAuthenticationConverter)
http.addFilterAt( authFilter, SecurityWebFiltersOrder.AUTHENTICATION)
You can use this approach to customize your AuthenticationConverter as I did to jwt based authentication to set the desired authentication object.
I am implementing Spring Integration for REST services. I am following XPadro's githib example - https://github.com/xpadro/spring-integration.
I have created simple read, write and update operations.
Examples taken from int-http-dsl project.
I want to implement spring-security with oath2. I am taking reference from http://docs.spring.io/spring-integration/reference/html/security.html.
I am not able to connect both together. Because below is how they map a request
#Bean
public IntegrationFlow httpGetFlow() {
return IntegrationFlows.from(httpGetGate()).channel("httpGetChannel").handle("personEndpoint", "get").get();
}
#Bean
public MessagingGatewaySupport httpGetGate() {
HttpRequestHandlingMessagingGateway handler = new HttpRequestHandlingMessagingGateway();
handler.setRequestMapping(createMapping(new HttpMethod[]{HttpMethod.GET}, "/persons/{personId}"));
handler.setPayloadExpression(parser().parseExpression("#pathVariables.personId"));
handler.setHeaderMapper(headerMapper());
return handler;
}
and below is how we can integrate security
#Bean
#SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = "ROLE_ADMIN")
public SubscribableChannel adminChannel() {
return new DirectChannel();
}
I am not able to find a way to create channels in first example so how to integrate that.
Am I going right direction or getting it all wrong?
Is there any better tutorials to handle spring-integration (http) with spring-security (using oauth)?
Spring Integration Java DSL allows to use external #Beans for message channels from the flow definition. So, your httpGetChannel may be declared and used like:
#Bean
#SecuredChannel(interceptor = "channelSecurityInterceptor", sendAccess = "ROLE_ADMIN")
public SubscribableChannel httpGetChannel() {
return new DirectChannel();
}
#Bean
public IntegrationFlow httpGetFlow() {
return IntegrationFlows.from(httpGetGate())
.channel(httpGetChannel())
.handle("personEndpoint", "get")
.get();
}
Feel free to raise a GitHub issue to make in the Framework something more obvious directly from the DSL's .channel() definition: https://github.com/spring-projects/spring-integration-java-dsl/issues
I am trying to access google and Twitter API for one of my Project. Both of these can give access to there API only using OAuth2.
Which is best OAuth client library available for the same?
Both API use OAuth 2 only and google deprecated the OAuth 1 support. It's always good to use latest version as it's more secure.
Update:
OAuth 2 has less round trips so it fast and quick.
You can use spring-security-oauth2. It is quite easy to implement all OAuth2RestOperations.
Create a OAuth2RestOperations bean which works almost same as RestTemplate(except for OAuth2 token handling part).
For example, if you are creating an rest call with Password credential authentication,
#Bean
public OAuth2RestOperations sampleROPCRestTemplate() {
return new OAuth2RestTemplate(sampleforcePasswordResourceDetails(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
}
#Bean
protected OAuth2ProtectedResourceDetails sampleforcePasswordResourceDetails() {
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setAccessTokenUri(tokenUrl);
resource.setClientId(clientId);
resource.setClientSecret(clientSecret);
resource.setUsername(username);
resource.setPassword(password);
resource.setClientAuthenticationScheme(AuthenticationScheme.form);
resource.setGrantType("password");
return resource;
}
Is it possible to use swagger as a documentation/testing tool for APIs that use OAuth2? I don't see anything on the swagger site (or anywhere else for that matter). Every usage I've seen uses either an API key, HTTP basic, or cookies.
I have been working along the same lines. Swagger will accept any header or URL defined api key or token. Adding a validation helper to the api and app is a standard approach.
Oauth does require a HTML review and or login to start the handshake aouth process. This means that a swagger api will need to support a web interface for a standard login and scope acceptance. Rolling oauth into swagger results in a few logic loops, which long term are not easy to support.
A different approach we are exploring is the option to let the api handle and store access tokens for a number of different oauth providers; GitHub, twitter and Facebook. This might result in login loops as well.
late to the party here but oAuth support is now in 1.3.0-RC1 of swagger-core. The javascript library which can support oAuth was released yesterday in swagger-js. Finally, the swagger-ui is in develop phase, and will soon have a oAuth implicit and server flow.
the blog´s post http://developers-blog.helloreverb.com/enabling-oauth-with-swagger/ cited by #fehguy shows an example of java code to include the authorization data in json generated by swagger, however my question was where it should be included with app with Spring, JAXRS and CXF. I didn´t find it in CXF + JAXRS Sample :https://github.com/swagger-api/swagger-core/tree/master/samples/java-jaxrs-cxf
However, looking for a bit more and gotcha !
https://github.com/swagger-api/swagger-core/blob/master/samples/java-jersey-spring/src/main/resources/beans-asset-ws.xml
Is necessary include a Bean with a class called Bootstrap (extends HttpServlet) and a static block !
Opinion: Maybe it would be more “spring-friendly” loaded from annotations by SwaggerConfig Scanner in Rest class instead a static block in a servlet.
#Configuration
public class SwaggerConfiguration {
#Bean
#DependsOn("jaxRsServer") //org.apache.cxf.endpoint.Server bean
public ServletContextInitializer initializer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
BeanConfig scanner = (BeanConfig) ScannerFactory.getScanner();
Swagger swagger = scanner.getSwagger();
servletContext.setAttribute("swagger", swagger);
}
};
}
#Bean
public Feature swaggerFeature() {
XSwagger2Feature feature = new XSwagger2Feature();
return feature;
}
#Bean
public FilterRegistrationBean swaggerApiFilter() {
ApiOriginFilter filter = new ApiOriginFilter();
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registrationBean;
}
public static class XSwagger2Feature extends Swagger2Feature {
#Override
protected void addSwaggerResource(Server server) {
super.addSwaggerResource(server);
BeanConfig scanner = (BeanConfig) ScannerFactory.getScanner();
Swagger swagger = scanner.getSwagger();
swagger.securityDefinition("api_key", new ApiKeyAuthDefinition("api_key", In.HEADER));
swagger.securityDefinition("petstore_auth",
new OAuth2Definition()
.implicit("http://petstore.swagger.io/api/oauth/dialog")
.scope("read:pets", "read your pets")
.scope("write:pets", "modify pets in your account"));
}
}
}
IOdocs from mashery seems to support OAuth, but it's quite different from swagger (redis, node, etc.). It's available on github.