There's a support for OpenAPI in this project. You can access OpenApi's access token
and make authenticated calls to OpenAPI resources right inside a LTI SpringBoot Security powered application.
This project has a fully functional implementation and can be used as an example
The support relies in Spring AOP and Oauth2. Just make sure there's these dependencies in your pom.xml
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
See pom.xml
in this project
In your ApplicationSecurity class:
-
Mark your Application with the annotations:
@EnableOAuth2Client
to allow oauth2 client calls
@EnableAspectJAutoProxy
to allow Advices in the app -
Define a
OAuth2ClientContext oauth2ClientContext
. This will be injected by Spring Security thanks to@EnableOAuth2Client
:@Autowired OAuth2ClientContext oauth2ClientContext;
-
Define the filter for redirecting to OpenAPI:
private OpenApiClientFilter openapiFilter() { OpenApiClientFilter openApiFilter = new OpenApiClientFilter(OPEN_API_URI); openApiFilter.setRestTemplate(openApiRestTemplate()); return openApiFilter; } @Bean @ConfigurationProperties("openapi.client") public AuthorizationCodeResourceDetails openapi() { return new AuthorizationCodeResourceDetails(); } @Bean public FilterRegistrationBean oauth2ClientFilterRegistration( OAuth2ClientContextFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(filter); registration.setOrder(-100); return registration; } @Bean public OAuth2RestOperations openApiRestTemplate() { return new OAuth2RestTemplate(openapi(), oauth2ClientContext); }
-
Add the filter to your filter chain:
@Override protected void configure(HttpSecurity http) throws Exception { http ... // your configuration .and().addFilterBefore(openapiFilter(), BasicAuthenticationFilter.class) ...// your configuration }
-
Define the advice bean:
@Bean public OpenApiAuthorizedAspect openApiAuthorizedAspect() { final OpenApiAuthorizedAspect openApiAuthorizedAspect = new OpenApiAuthorizedAspect(); openApiAuthorizedAspect.setRedirectUri("/login/openapi"); return openApiAuthorizedAspect; }
The URI in
openApiAuthorizedAspect.setRedirectUri
MUST be the same as the uri of theOpenApiClientFilter
.
See edu.uoc.elearn.lti.provider.config.ApplicationSecurity.java
in this project
Add to your application.properties
the configuration for OpenAPI:
# Open API Client Configuration
openapi.client.accessTokenUri=https://cv.uoc.edu/webapps/uocapi/oauth/token
openapi.client.userAuthorizationUri=https://cv.uoc.edu/webapps/uocapi/oauth/authorize
openapi.client.tokenName=access_token
openapi.client.clientAuthenticationScheme=form
openapi.client.authenticationScheme=query
openapi.client.scope=READ READ_GRADEBOOK
Adapt the scope's to your application's needs.
Adapt the URL's as well if you are targeting others environments.
See application.properties
in this project
We store client id and secret in a configuration file (typically application-{devel|pro}.yml
):
# Open Api client
openapi:
client:
clientId: "your_client_id"
clientSecret: "your_secret"
See application.properties
in this project
The annotation edu.uoc.elearn.openapi.spring.OpenApiAuthorized
defines methods to be called only when the application has been authorized by the user in OpenApi.
If the application hasn't been authorized (and the application has been configured the filter properly), the application redirects itself to the authorization process in OpenAPI
See edu.uoc.elearn.lti.provider.controller.UserController.java
in this project
If you want OpenApi to redirect exactly where you were, just add a parameter HttpServletRequest request
to your edu.uoc.elearn.openapi.spring.OpenApiAuthorized
's annotated method
See edu.uoc.elearn.lti.provider.controller.UserController.java
in this project
Add urls in application.properties
:
openapi.client.resource.user=https://cv.uoc.edu/webapps/uocapi/api/v1/user
-
Add beans in your controller:
@Autowired OAuth2RestOperations openApiRestTemplate; @Value("${openapi.client.resource.user}") private String userResourceUrl;
-
Make the call:
Map userData = openApiRestTemplate.getForObject(userResourceUrl, Map.class);
See edu.uoc.elearn.lti.provider.controller.UserController.java
in this project
We should definitely improve this, making a client library with objects