>.
Lastly, you can customize the role mapping behavior by providing your own Spring bean definition that
-extends Spring Security OAuth's `AuthoritiesExtractor` interface. In that case,
+extends Spring Cloud Data Flow's `AuthorityMapper` interface. In that case,
the custom bean definition takes precedence over the default one provided by
Spring Cloud Data Flow.
@@ -635,6 +658,8 @@ spring:
security:
authorization:
enabled: true
+ loginUrl: "/"
+ permit-all-paths: "/authenticate,/security/info,/assets/**,/dashboard/logout-success-oauth.html,/favicon.ico"
rules:
# About
@@ -667,6 +692,7 @@ spring:
- GET /jobs/executions => hasRole('ROLE_VIEW')
- PUT /jobs/executions/** => hasRole('ROLE_MODIFY')
- GET /jobs/executions/** => hasRole('ROLE_VIEW')
+ - GET /jobs/thinexecutions => hasRole('ROLE_VIEW')
# Batch Job Instances
@@ -700,6 +726,9 @@ spring:
- GET /streams/validation/ => hasRole('ROLE_VIEW')
- GET /streams/validation/* => hasRole('ROLE_VIEW')
+ # Stream Logs
+ - GET /streams/logs/* => hasRole('ROLE_VIEW')
+
# Task Definitions
- POST /tasks/definitions => hasRole('ROLE_CREATE')
@@ -712,6 +741,7 @@ spring:
- GET /tasks/executions => hasRole('ROLE_VIEW')
- GET /tasks/executions/* => hasRole('ROLE_VIEW')
- POST /tasks/executions => hasRole('ROLE_DEPLOY')
+ - POST /tasks/executions/* => hasRole('ROLE_DEPLOY')
- DELETE /tasks/executions/* => hasRole('ROLE_DESTROY')
# Task Schedules
@@ -723,11 +753,18 @@ spring:
- POST /tasks/schedules => hasRole('ROLE_SCHEDULE')
- DELETE /tasks/schedules/* => hasRole('ROLE_SCHEDULE')
+ # Task Platform Account List */
+
+ - GET /tasks/platforms => hasRole('ROLE_VIEW')
+
# Task Validations
- GET /tasks/validation/ => hasRole('ROLE_VIEW')
- GET /tasks/validation/* => hasRole('ROLE_VIEW')
+ # Task Logs
+ - GET /tasks/logs/* => hasRole('ROLE_VIEW')
+
# Tools
- POST /tools/** => hasRole('ROLE_VIEW')
@@ -798,44 +835,105 @@ While the UAA is used by https://www.cloudfoundry.org/[Cloud Foundry],
it is also a fully featured stand alone OAuth2 server with enterprise features such as
https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md[LDAP integration].
+===== Requirements
+
Checkout, Build and Run UAA:
+- Make sure you use Java 8
+- https://git-scm.com/[Git] installed
+- You need the https://github.com/cloudfoundry/cf-uaac[CloudFoundry UAA Command Line Client] installed
+- Use a different host name for UAA when running on the same machine, e.g. `http://uaa/`
+
+In case you run into issues installing _uaac_, you may have to set the `GEM_HOME` environment
+variable:
+
[source,bash]
----
-$ git clone https://github.com/cloudfoundry/uaa.git
-$ cd uaa/
-$ ./gradlew run
+export GEM_HOME="$HOME/.gem"
+----
+
+and add `~/.gem/gems/cf-uaac-4.2.0/bin` to your path.
+
+===== Prepare UAA for JWT
+
+As the UAA is an OpenID provider it uses JSON Web Tokens (JWT) it needs to have
+a private key for signing those JWTs:
+
+[source,bash]
+----
+openssl genrsa -out signingkey.pem 2048
+openssl rsa -in signingkey.pem -pubout -out verificationkey.pem
+export JWT_TOKEN_SIGNING_KEY=$(cat signingkey.pem)
+export JWT_TOKEN_VERIFICATION_KEY=$(cat verificationkey.pem)
+----
+
+Later, once the UAA is started you can see the keys when accessing `http://uaa:8080/uaa/token_keys`
+
+===== Download + Start UAA
+
+[source,bash]
+----
+git clone https://github.com/pivotal/uaa-bundled.git
+cd uaa-bundled
+./mvnw clean install
+java -jar target/uaa-bundled-1.0.0.BUILD-SNAPSHOT.jar
+----
+
+The configuration of the UAA is driven by either a Yaml file `uaa.yml` or you can script the configuration
+using the UAA Command Line Client:
+
+[source,bash]
+----
+uaac target http://uaa:8080/uaa
+uaac token client get admin -s adminsecret
+uaac client add dataflow \
+ --name dataflow \
+ --secret dataflow \
+ --scope cloud_controller.read,cloud_controller.write,openid,password.write,scim.userids,foo.create,foo.view \
+ --authorized_grant_types password,authorization_code,client_credentials,refresh_token \
+ --authorities uaa.resource,dataflow.create,dataflow.deploy,dataflow.destroy,dataflow.manage,dataflow.modify,dataflow.schedule,dataflow.view,foo.view,foo.create\
+ --redirect_uri http://localhost:9393/login \
+ --autoapprove openid \
+
+uaac group add "foo.view"
+uaac group add "foo.create"
+
+uaac user add springrocks -p mysecret --emails springrocks@someplace.com
+uaac user add vieweronly -p mysecret --emails mrviewer@someplace.com
+
+uaac member add "foo.view" springrocks
+uaac member add "foo.create" springrocks
+uaac member add "foo.view" vieweronly
----
-IMPORTANT: The UAA requires *Java 8*.
+This script will set up the dataflow client as well as 2 users:
-The configuration of the UAA is driven by a
-https://github.com/cloudfoundry/uaa/blob/develop/uaa/src/main/resources/uaa.yml[uaa.yml]
-file. You can provide custom configuration but in this case we will use the
-embedded default configuration that provides also a default user:
+- User _springrocks_ will have both scopes `foo.view` and `foo.create`
+- User _vieweronly_ will only have one scope `foo.view`
+Once added, you can quickly double-check that the UAA has the users created:
[source,bash]
----
-curl -v -d"username=marissa&password=koala&client_id=app&grant_type=password" -u "app:appclientsecret" http://localhost:8080/uaa/oauth/token -d 'token_format=opaque'
+curl -v -d"username=springrocks&password=mysecret&client_id=dataflow&grant_type=password" -u "dataflow:dataflow" http://uaa:8080/uaa/oauth/token -d 'token_format=opaque'
----
This should produce output similar to the following:
[source,bash]
----
-* Trying ::1...
+* Trying 127.0.0.1...
* TCP_NODELAY set
-* Connected to localhost (::1) port 8080 (#0)
-* Server auth using Basic with user 'app'
+* Connected to uaa (127.0.0.1) port 8080 (#0)
+* Server auth using Basic with user 'dataflow'
> POST /uaa/oauth/token HTTP/1.1
-> Host: localhost:8080
-> Authorization: Basic YXBwOmFwcGNsaWVudHNlY3JldA==
+> Host: uaa:8080
+> Authorization: Basic ZGF0YWZsb3c6ZGF0YWZsb3c=
> User-Agent: curl/7.54.0
> Accept: */*
-> Content-Length: 85
+> Content-Length: 97
> Content-Type: application/x-www-form-urlencoded
>
-* upload completely sent off: 85 out of 85 bytes
+* upload completely sent off: 97 out of 97 bytes
< HTTP/1.1 200
< Cache-Control: no-store
< Pragma: no-cache
@@ -844,10 +942,10 @@ This should produce output similar to the following:
< X-Content-Type-Options: nosniff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
-< Date: Mon, 03 Dec 2018 23:58:41 GMT
+< Date: Thu, 31 Oct 2019 21:22:59 GMT
<
-* Connection #0 to host localhost left intact
-{"access_token":"0f935cea42fd4516bb36e4088f6d7c44","token_type":"bearer","id_token":"eyJhbGciOiJIUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvdWFhL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.eyJzdWIiOiI1ODExMWNlNC02NGRlLTQ3ZDYtYjZiZi0wZDRhNDFhNGFlMDAiLCJhdWQiOlsiYXBwIl0sImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC91YWEvb2F1dGgvdG9rZW4iLCJleHAiOjE1NDM5MjQ3MjEsImlhdCI6MTU0Mzg4MTUyMSwiYW1yIjpbInB3ZCJdLCJhenAiOiJhcHAiLCJzY29wZSI6WyJvcGVuaWQiXSwiZW1haWwiOiJtYXJpc3NhQHRlc3Qub3JnIiwiemlkIjoidWFhIiwib3JpZ2luIjoidWFhIiwianRpIjoiMGY5MzVjZWE0MmZkNDUxNmJiMzZlNDA4OGY2ZDdjNDQiLCJwcmV2aW91c19sb2dvbl90aW1lIjoxNTQzODgxMTk1NzU2LCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiY2xpZW50X2lkIjoiYXBwIiwiY2lkIjoiYXBwIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9uYW1lIjoibWFyaXNzYSIsInJldl9zaWciOiI1ZmI4N2M1NiIsInVzZXJfaWQiOiI1ODExMWNlNC02NGRlLTQ3ZDYtYjZiZi0wZDRhNDFhNGFlMDAiLCJhdXRoX3RpbWUiOjE1NDM4ODE1MjF9.qSxoygd7LUUJSEN0wGI3-U0x2tYZzHnTDuzk6AJUfBk","refresh_token":"d106513b98804a508c35d3f7b656a7fe-r","expires_in":43199,"scope":"scim.userids openid cloud_controller.read password.write cloud_controller.write","jti":"0f935cea42fd4516bb36e4088f6d7c44"}
+* Connection #0 to host uaa left intact
+{"access_token":"0329c8ecdf594ee78c271e022138be9d","token_type":"bearer","id_token":"eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvdWFhL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.eyJzdWIiOiJlZTg4MDg4Ny00MWM2LTRkMWQtYjcyZC1hOTQ4MmFmNGViYTQiLCJhdWQiOlsiZGF0YWZsb3ciXSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDkwL3VhYS9vYXV0aC90b2tlbiIsImV4cCI6MTU3MjYwMDE3OSwiaWF0IjoxNTcyNTU2OTc5LCJhbXIiOlsicHdkIl0sImF6cCI6ImRhdGFmbG93Iiwic2NvcGUiOlsib3BlbmlkIl0sImVtYWlsIjoic3ByaW5ncm9ja3NAc29tZXBsYWNlLmNvbSIsInppZCI6InVhYSIsIm9yaWdpbiI6InVhYSIsImp0aSI6IjAzMjljOGVjZGY1OTRlZTc4YzI3MWUwMjIxMzhiZTlkIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImNsaWVudF9pZCI6ImRhdGFmbG93IiwiY2lkIjoiZGF0YWZsb3ciLCJncmFudF90eXBlIjoicGFzc3dvcmQiLCJ1c2VyX25hbWUiOiJzcHJpbmdyb2NrcyIsInJldl9zaWciOiJlOTkyMDQxNSIsInVzZXJfaWQiOiJlZTg4MDg4Ny00MWM2LTRkMWQtYjcyZC1hOTQ4MmFmNGViYTQiLCJhdXRoX3RpbWUiOjE1NzI1NTY5Nzl9.bqYvicyCPB5cIIu_2HEe5_c7nSGXKw7B8-reTvyYjOQ2qXSMq7gzS4LCCQ-CMcb4IirlDaFlQtZJSDE-_UsM33-ThmtFdx--TujvTR1u2nzot4Pq5A_ThmhhcCB21x6-RNNAJl9X9uUcT3gKfKVs3gjE0tm2K1vZfOkiGhjseIbwht2vBx0MnHteJpVW6U0pyCWG_tpBjrNBSj9yLoQZcqrtxYrWvPHaa9ljxfvaIsOnCZBGT7I552O1VRHWMj1lwNmRNZy5koJFPF7SbhiTM8eLkZVNdR3GEiofpzLCfoQXrr52YbiqjkYT94t3wz5C6u1JtBtgc2vq60HmR45bvg","refresh_token":"6ee95d017ada408697f2d19b04f7aa6c-r","expires_in":43199,"scope":"scim.userids openid foo.create cloud_controller.read password.write cloud_controller.write foo.view","jti":"0329c8ecdf594ee78c271e022138be9d"}
----
Using `token_format` parameter you can requested token to be either:
@@ -855,95 +953,89 @@ Using `token_format` parameter you can requested token to be either:
- opaque
- jwt
-In order to configure the UAA, it is recommended to use the `uaac` command line tool and target the UAA server:
-
-[source,bash]
-----
-$ gem install cf-uaac
-$ uaac target http://localhost:8080/uaa
-----
-
-Check out the user details of user `marissa`:
-
-[source,bash]
-----
-$ uaac token owner get cf marissa -s "" -p koala
-$ uaac contexts
-----
-
-This should also provide the relevant token details. Next, switch to the
-admin user (password is `adminsecret`):
-
-[source,bash]
-----
-$ uaac token client get admin -s adminsecret
-----
-
-Get a list of all configured clients:
-
-[source,bash]
-----
-$ uaac clients
-----
-
-This returns the interesting client app among others:
+===== Start Skipper
[source,bash]
----
-…
- app
- scope: cloud_controller.read cloud_controller.write openid password.write scim.userids organizations.acme
- resource_ids: none
- authorized_grant_types: password implicit authorization_code client_credentials refresh_token
- redirect_uri: http://localhost:8080/** http://localhost:8080/app/
- autoapprove: openid
- authorities: uaa.resource
- name: The Ultimate Oauth App
- signup_redirect_url: http://localhost:8080/app/
- change_email_redirect_url: http://localhost:8080/app/
- lastmodified: 1543879731285
-…
+git clone https://github.com/spring-cloud/spring-cloud-skipper.git
+cd spring-cloud/spring-cloud-skipper
+./mvnw clean package -DskipTests=true
+java -jar spring-cloud-skipper-server/target/spring-cloud-skipper-server-2.2.0.BUILD-SNAPSHOT.jar
----
-We are going to use that `app` for Spring Cloud Data Flow but need to update
-the `redirect_uri`. We will also update the client secret:
+===== Start Spring Cloud Data Flow
[source,bash]
----
-$ uaac client update app --redirect_uri http://localhost:9393/login
-$ uaac secret set app --secret dataflow
+git clone https://github.com/spring-cloud/spring-cloud-dataflow.git
+cd spring-cloud-dataflow
+./mvnw clean package -DskipTests=true
+cd ..
----
-Now we can update the relavant OAuth configuration in Spring Cloud Data Flow:
+Create a yaml file scdf.yml with the following contents:
[source,yaml]
----
-security:
- oauth2:
- client:
- client-id: app
- client-secret: dataflow
- scope: openid # <1>
- access-token-uri: http://localhost:8080/uaa/oauth/token
- user-authorization-uri: http://localhost:8080/uaa/oauth/authorize
- resource:
- user-info-uri: http://localhost:8080/uaa/userinfo # <2>
- token-info-uri: http://localhost:8080/uaa/check_token # <3>
+spring:
+ cloud:
+ dataflow:
+ security:
+ authorization:
+ provider-role-mappings:
+ uaa:
+ map-oauth-scopes: true
+ role-mappings:
+ ROLE_CREATE: foo.create
+ ROLE_DEPLOY: foo.create
+ ROLE_DESTROY: foo.create
+ ROLE_MANAGE: foo.create
+ ROLE_MODIFY: foo.create
+ ROLE_SCHEDULE: foo.create
+ ROLE_VIEW: foo.view
+ security:
+ oauth2:
+ client:
+ registration:
+ uaa:
+ redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
+ authorization-grant-type: authorization_code
+ client-id: dataflow
+ client-secret: dataflow
+ scope: <1>
+ - openid
+ - foo.create
+ - foo.view
+ provider:
+ uaa:
+ jwk-set-uri: http://uaa:8080/uaa/token_keys
+ token-uri: http://uaa:8080/uaa/oauth/token
+ user-info-uri: http://uaa:8080/uaa/userinfo <2>
+ user-name-attribute: user_name
+ authorization-uri: http://uaa:8080/uaa/oauth/authorize
+ resourceserver:
+ opaquetoken: <3>
+ introspection-uri: http://uaa:8080/uaa/introspect
+ client-id: dataflow
+ client-secret: dataflow
----
<1> If you use scopes to identify roles, please make sure to also request
-the relevant scopes, e.g `dataflow.view`, `dataflow.create` etc.
+ the relevant scopes, e.g `dataflow.view`, `dataflow.create` and don't forget to request the `openid` scope
<2> Used to retrieve profile information, e.g. username for display purposes (mandatory)
<3> Used for token introspection and validation (mandatory)
-The `token-info-uri` property is especially important when passing an externally retrieved OAuth Access Token
-to Spring Cloud Data Flow. In that case Spring Cloud Data Flow will take the OAuth Access Token via the
-https://github.com/spring-cloud/spring-cloud-common-security-config/blob/master/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/support/TokenValidatingUserInfoTokenServices.java[TokenValidatingUserInfoTokenServices]
-, and use the UAA's
-https://docs.cloudfoundry.org/api/uaa/version/4.27.0/index.html#check-token[Check Token Endpoint]
+The `introspection-uri` property is especially important when passing an externally retrieved (opaque)
+OAuth Access Token to Spring Cloud Data Flow. In that case Spring Cloud Data Flow will take the OAuth Access,
+and use the UAA's https://docs.cloudfoundry.org/api/uaa/version/74.4.0/index.html#introspect-token[Introspect Token Endpoint]
to not only check the validity of the token but also retrieve the associated OAuth scopes from the UAA
-and store the successful authentication in Spring Cloud Data Flow's
-https://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/TokenStore.html[TokenStore].
+
+Finally startup Spring Cloud Data Flow:
+
+[source,bash]
+----
+java -jar spring-cloud-dataflow/spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.3.0.BUILD-SNAPSHOT.jar --spring.config.additional-location=scdf.yml
+----
[[configuration-security-role-mapping]]
===== Role Mappings
@@ -951,7 +1043,7 @@ https://docs.spring.io/spring-security/oauth/apidocs/org/springframework/securit
By default all roles are assigned to users that login to Spring Cloud Data Flow.
However, you can set the property:
-`spring.cloud.dataflow.security.authorization.map-oauth-scopes: true`
+`spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.map-oauth-scopes: true`
This will instruct the underlying `DefaultAuthoritiesExtractor` to map
OAuth scopes to the respective authorities. The following scopes are supported:
@@ -970,21 +1062,20 @@ Additionally you can also map arbitrary scopes to each of the Data Flow roles:
----
spring:
cloud:
- deployer:
- local:
- free-disk-space-percentage: 0
dataflow:
security:
authorization:
- map-oauth-scopes: true # <1>
- role-mappings:
- ROLE_CREATE: dataflow.create # <2>
- ROLE_DEPLOY: dataflow.deploy
- ROLE_DESTROY: dataflow.destoy
- ROLE_MANAGE: dataflow.manage
- ROLE_MODIFY: dataflow.modify
- ROLE_SCHEDULE: dataflow.schedule
- ROLE_VIEW: dataflow.view
+ provider-role-mappings:
+ uaa:
+ map-oauth-scopes: true # <1>
+ role-mappings:
+ ROLE_CREATE: dataflow.create # <2>
+ ROLE_DEPLOY: dataflow.deploy
+ ROLE_DESTROY: dataflow.destoy
+ ROLE_MANAGE: dataflow.manage
+ ROLE_MODIFY: dataflow.modify
+ ROLE_SCHEDULE: dataflow.schedule
+ ROLE_VIEW: dataflow.view
----
<1> Enables explicit mapping support from OAuth scopes to Data Flow roles
diff --git a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/CloudFoundryOAuthSecurityConfiguration.java b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/CloudFoundryOAuthSecurityConfiguration.java
index 2c4933dfb1..2b08cddf31 100644
--- a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/CloudFoundryOAuthSecurityConfiguration.java
+++ b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/CloudFoundryOAuthSecurityConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 the original author or authors.
+ * Copyright 2017-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,20 +24,19 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor;
-import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.cloud.common.security.OAuthSecurityConfiguration;
-import org.springframework.cloud.common.security.support.DefaultAuthoritiesExtractor;
+import org.springframework.cloud.common.security.support.CustomAuthoritiesOpaqueTokenIntrospector;
+import org.springframework.cloud.common.security.support.DefaultAuthoritiesMapper;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.common.security.support.OnOAuth2SecurityEnabled;
-import org.springframework.cloud.dataflow.server.config.cloudfoundry.security.support.CloudFoundryDataflowAuthoritiesExtractor;
-import org.springframework.cloud.dataflow.server.config.cloudfoundry.security.support.CloudFoundryPrincipalExtractor;
+import org.springframework.cloud.dataflow.server.config.cloudfoundry.security.support.CloudFoundryDataflowAuthoritiesMapper;
import org.springframework.cloud.dataflow.server.config.cloudfoundry.security.support.CloudFoundrySecurityService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.springframework.security.oauth2.client.OAuth2RestTemplate;
+import org.springframework.web.client.RestTemplate;
/**
* When running inside Cloud Foundry, this {@link Configuration} class will reconfigure
@@ -48,7 +47,7 @@
* {@code Space Developers} have access to the underlying REST API's.
*
* For this to happen, a REST call will be made to the Cloud Foundry Permissions API via
- * CloudFoundrySecurityService inside the {@link DefaultAuthoritiesExtractor}.
+ * CloudFoundrySecurityService inside the {@link DefaultAuthoritiesMapper}.
*
* If the user has the respective permissions, the CF_SPACE_DEVELOPER_ROLE will be
* assigned to the user.
@@ -68,26 +67,16 @@ public class CloudFoundryOAuthSecurityConfiguration {
private static final Logger logger = LoggerFactory.getLogger(CloudFoundryOAuthSecurityConfiguration.class);
@Autowired
- private UserInfoTokenServices userInfoTokenServices;
+ private CustomAuthoritiesOpaqueTokenIntrospector customAuthoritiesOpaqueTokenIntrospector;
@Autowired(required = false)
- private CloudFoundryDataflowAuthoritiesExtractor cloudFoundryDataflowAuthoritiesExtractor;
-
- @Autowired(required = false)
- private PrincipalExtractor principalExtractor;
+ private CloudFoundryDataflowAuthoritiesMapper cloudFoundryDataflowAuthoritiesExtractor;
@PostConstruct
public void init() {
if (this.cloudFoundryDataflowAuthoritiesExtractor != null) {
logger.info("Setting up Cloud Foundry AuthoritiesExtractor for UAA.");
- this.userInfoTokenServices.setAuthoritiesExtractor(this.cloudFoundryDataflowAuthoritiesExtractor);
- }
- if (this.principalExtractor != null) {
- logger.info("Setting up Cloud Foundry PrincipalExtractor.");
- this.userInfoTokenServices.setPrincipalExtractor(this.principalExtractor);
- }
- else {
- this.userInfoTokenServices.setPrincipalExtractor(new CloudFoundryPrincipalExtractor());
+ this.customAuthoritiesOpaqueTokenIntrospector.setAuthorityMapper(this.cloudFoundryDataflowAuthoritiesExtractor);
}
}
@@ -101,17 +90,19 @@ public class CloudFoundryUAAConfiguration {
@Value("${vcap.application.application_id}")
private String applicationId;
- @Autowired
- private OAuth2RestTemplate oAuth2RestTemplate;
-
@Bean
- public CloudFoundryDataflowAuthoritiesExtractor authoritiesExtractor() {
- return new CloudFoundryDataflowAuthoritiesExtractor(cloudFoundrySecurityService());
+ public CloudFoundryDataflowAuthoritiesMapper authoritiesExtractor(
+ CloudFoundrySecurityService cloudFoundrySecurityService
+ ) {
+ return new CloudFoundryDataflowAuthoritiesMapper(cloudFoundrySecurityService);
}
@Bean
- public CloudFoundrySecurityService cloudFoundrySecurityService() {
- return new CloudFoundrySecurityService(this.oAuth2RestTemplate, this.cloudControllerUrl,
+ public CloudFoundrySecurityService cloudFoundrySecurityService(
+ OAuth2TokenUtilsService oauth2TokenUtilsService,
+ RestTemplate restTemplate) {
+ return new CloudFoundrySecurityService(oauth2TokenUtilsService, restTemplate,
+ this.cloudControllerUrl,
this.applicationId);
}
diff --git a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryDataflowAuthoritiesExtractor.java b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryDataflowAuthoritiesMapper.java
similarity index 70%
rename from spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryDataflowAuthoritiesExtractor.java
rename to spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryDataflowAuthoritiesMapper.java
index c27c986ad4..38f0915cc4 100644
--- a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryDataflowAuthoritiesExtractor.java
+++ b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryDataflowAuthoritiesMapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 the original author or authors.
+ * Copyright 2017-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,15 +16,16 @@
package org.springframework.cloud.dataflow.server.config.cloudfoundry.security.support;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import java.util.Map;
+import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
+import org.springframework.cloud.common.security.support.AuthoritiesMapper;
import org.springframework.cloud.common.security.support.CoreSecurityRoles;
import org.springframework.cloud.common.security.support.SecurityConfigUtils;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
@@ -34,21 +35,21 @@
import org.springframework.util.StringUtils;
/**
- * This Spring Cloud Data Flow {@link AuthoritiesExtractor} will assign all
+ * This Spring Cloud Data Flow {@link AuthoritiesMapper} will assign all
* {@link CoreSecurityRoles} to the authenticated OAuth2 user IF the user is a "Space
* Developer" in Cloud Foundry.
*
* @author Gunnar Hillert
*
*/
-public class CloudFoundryDataflowAuthoritiesExtractor implements AuthoritiesExtractor {
+public class CloudFoundryDataflowAuthoritiesMapper implements AuthoritiesMapper {
private static final Logger logger = LoggerFactory
- .getLogger(CloudFoundryDataflowAuthoritiesExtractor.class);
+ .getLogger(CloudFoundryDataflowAuthoritiesMapper.class);
private final CloudFoundrySecurityService cloudFoundrySecurityService;
- public CloudFoundryDataflowAuthoritiesExtractor(CloudFoundrySecurityService cloudFoundrySecurityService) {
+ public CloudFoundryDataflowAuthoritiesMapper(CloudFoundrySecurityService cloudFoundrySecurityService) {
this.cloudFoundrySecurityService = cloudFoundrySecurityService;
}
@@ -60,24 +61,29 @@ public CloudFoundryDataflowAuthoritiesExtractor(CloudFoundrySecurityService clou
* @param map Must not be null. Is only used for logging
*/
@Override
- public List extractAuthorities(Map map) {
- Assert.notNull(map, "The map argument must not be null.");
+ public Set mapScopesToAuthorities(Set scopes) {
+ Assert.notNull(scopes, "The scopes argument must not be null.");
if (cloudFoundrySecurityService.isSpaceDeveloper()) {
final List rolesAsStrings = new ArrayList<>();
- final List grantedAuthorities = Stream.of(CoreSecurityRoles.values())
+ final Set grantedAuthorities = Stream.of(CoreSecurityRoles.values())
.map(roleEnum -> {
final String roleName = SecurityConfigUtils.ROLE_PREFIX + roleEnum.getKey();
rolesAsStrings.add(roleName);
return new SimpleGrantedAuthority(roleName);
})
- .collect(Collectors.toList());
- logger.info("Adding ALL roles {} to Cloud Foundry Space Developer user {}",
- StringUtils.collectionToCommaDelimitedString(rolesAsStrings), map);
+ .collect(Collectors.toSet());
+ logger.info("Adding ALL roles {} to Cloud Foundry Space Developer user.",
+ StringUtils.collectionToCommaDelimitedString(rolesAsStrings));
return grantedAuthorities;
}
else {
- return new ArrayList<>(0);
+ return Collections.emptySet();
}
}
+
+ @Override
+ public Set mapScopesToAuthorities(String providerId, Set scopes) {
+ throw new UnsupportedOperationException("Don't call this AuthoritiesMapper with a providerId.");
+ }
}
diff --git a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryPrincipalExtractor.java b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryPrincipalExtractor.java
deleted file mode 100644
index 20f0d85e43..0000000000
--- a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundryPrincipalExtractor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2017 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.cloud.dataflow.server.config.cloudfoundry.security.support;
-
-import java.util.Map;
-
-import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor;
-
-/**
- * A Cloud Foundry specific {@link PrincipalExtractor} that extracts the username.
- *
- * @author Gunnar Hillert
- *
- */
-public class CloudFoundryPrincipalExtractor implements PrincipalExtractor {
-
- private static final String[] PRINCIPAL_KEYS = new String[] { "user_name", "user", "username",
- "userid", "user_id", "login", "id", "name" };
-
- @Override
- public Object extractPrincipal(Map map) {
- for (String key : PRINCIPAL_KEYS) {
- if (map.containsKey(key)) {
- return map.get(key);
- }
- }
- return null;
- }
-
-}
diff --git a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundrySecurityService.java b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundrySecurityService.java
index c57a3a53e4..15f00963e4 100644
--- a/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundrySecurityService.java
+++ b/spring-cloud-dataflow-platform-cloudfoundry/src/main/java/org/springframework/cloud/dataflow/server/config/cloudfoundry/security/support/CloudFoundrySecurityService.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 the original author or authors.
+ * Copyright 2017-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,13 +22,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
-import org.springframework.security.oauth2.client.OAuth2RestTemplate;
-import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.util.Assert;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.RestTemplate;
/**
* Cloud Foundry security service to handle REST calls to the cloud controller and UAA.
@@ -42,20 +42,24 @@ public class CloudFoundrySecurityService {
private static final Logger logger = LoggerFactory.getLogger(CloudFoundrySecurityService.class);
- private final OAuth2RestTemplate oAuth2RestTemplate;
+ private final OAuth2TokenUtilsService oauth2TokenUtilsService;
+ private final RestTemplate restTemplate;
private final String cloudControllerUrl;
private final String applicationId;
- public CloudFoundrySecurityService(OAuth2RestTemplate oAuth2RestTemplate, String cloudControllerUrl,
+ public CloudFoundrySecurityService(OAuth2TokenUtilsService oauth2TokenUtilsService,
+ RestTemplate restTemplate, String cloudControllerUrl,
String applicationId) {
- Assert.notNull(oAuth2RestTemplate, "OAuth2RestTemplate must not be null.");
+ Assert.notNull(oauth2TokenUtilsService, "oauth2TokenUtilsService must not be null.");
+ Assert.notNull(restTemplate, "restTemplate must not be null.");
Assert.notNull(cloudControllerUrl, "CloudControllerUrl must not be null.");
Assert.notNull(applicationId, "ApplicationId must not be null.");
- this.oAuth2RestTemplate = oAuth2RestTemplate;
+ this.oauth2TokenUtilsService = oauth2TokenUtilsService;
this.cloudControllerUrl = cloudControllerUrl;
this.applicationId = applicationId;
+ this.restTemplate = restTemplate;
}
/**
@@ -66,10 +70,10 @@ public CloudFoundrySecurityService(OAuth2RestTemplate oAuth2RestTemplate, String
* @return true of the user is a space developer in Cloud Foundry
*/
public boolean isSpaceDeveloper() {
- final OAuth2AccessToken accessToken = this.oAuth2RestTemplate.getAccessToken();
- logger.info("The accessToken is: " + accessToken.getValue());
+ final String accessToken = this.oauth2TokenUtilsService.getAccessTokenOfAuthenticatedUser();
+ logger.info("The accessToken is: " + accessToken);
final AccessLevel accessLevel = getAccessLevel(
- accessToken.getValue(), applicationId);
+ accessToken, applicationId);
if (AccessLevel.FULL.equals(accessLevel)) {
return true;
@@ -93,7 +97,7 @@ public AccessLevel getAccessLevel(String token, String applicationId)
logger.info("Using PermissionsUri: " + permissionsUri);
RequestEntity> request = RequestEntity.get(permissionsUri)
.header("Authorization", "bearer " + token).build();
- Map, ?> body = this.oAuth2RestTemplate.exchange(request, Map.class).getBody();
+ Map, ?> body = this.restTemplate.exchange(request, Map.class).getBody();
if (Boolean.TRUE.equals(body.get("read_sensitive_data"))) {
return AccessLevel.FULL;
}
diff --git a/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/config/DataFlowClientProperties.java b/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/config/DataFlowClientProperties.java
index 334e79aa2a..6c92d2f096 100644
--- a/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/config/DataFlowClientProperties.java
+++ b/spring-cloud-dataflow-rest-client/src/main/java/org/springframework/cloud/dataflow/rest/client/config/DataFlowClientProperties.java
@@ -37,7 +37,7 @@ public class DataFlowClientProperties {
/**
* Skip Ssl validation.
*/
- private boolean skipSslValidation = true;
+ private boolean skipSslValidation;
/**
diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java
index 0ef33da502..07df215189 100644
--- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java
+++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/DataFlowControllerAutoConfiguration.java
@@ -35,6 +35,7 @@
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.common.security.AuthorizationProperties;
import org.springframework.cloud.common.security.support.OAuth2AccessTokenProvidingClientHttpRequestInterceptor;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.common.security.support.SecurityStateBean;
import org.springframework.cloud.dataflow.audit.repository.AuditRecordRepository;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
@@ -363,7 +364,8 @@ public StreamDeploymentController updatableStreamDeploymentController(
@Bean
public SkipperClient skipperClient(SkipperClientProperties properties,
- RestTemplateBuilder restTemplateBuilder, ObjectMapper objectMapper) {
+ RestTemplateBuilder restTemplateBuilder, ObjectMapper objectMapper,
+ @Nullable OAuth2TokenUtilsService oauth2TokenUtilsService) {
// TODO (Tzolov) review the manual Hal convertion configuration
objectMapper.registerModule(new Jackson2HalModule());
@@ -373,7 +375,7 @@ public SkipperClient skipperClient(SkipperClientProperties properties,
RestTemplate restTemplate = restTemplateBuilder
.errorHandler(new SkipperClientResponseErrorHandler(objectMapper))
- .interceptors(new OAuth2AccessTokenProvidingClientHttpRequestInterceptor())
+ .interceptors(new OAuth2AccessTokenProvidingClientHttpRequestInterceptor(oauth2TokenUtilsService))
.messageConverters(Arrays.asList(new StringHttpMessageConverter(),
new MappingJackson2HttpMessageConverter(objectMapper)))
.build();
diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/features/TaskConfiguration.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/features/TaskConfiguration.java
index 0a581ef3b4..e4e10f485b 100644
--- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/features/TaskConfiguration.java
+++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/config/features/TaskConfiguration.java
@@ -27,6 +27,7 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
import org.springframework.cloud.dataflow.configuration.metadata.ApplicationConfigurationMetadataResolver;
import org.springframework.cloud.dataflow.core.TaskPlatform;
@@ -181,12 +182,14 @@ public TaskExecutionService taskService(LauncherRepository launcherRepository,
TaskAppDeploymentRequestCreator taskAppDeploymentRequestCreator,
TaskExplorer taskExplorer,
DataflowTaskExecutionDao dataflowTaskExecutionDao,
- DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao) {
+ DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao,
+ @Nullable OAuth2TokenUtilsService oauth2TokenUtilsService) {
return new DefaultTaskExecutionService(
launcherRepository, auditRecordService, taskRepository,
taskExecutionInfoService, taskDeploymentRepository, taskExecutionRepositoryService,
taskAppDeploymentRequestCreator, taskExplorer, dataflowTaskExecutionDao,
- dataflowTaskExecutionMetadataDao);
+ dataflowTaskExecutionMetadataDao, oauth2TokenUtilsService);
+
}
@Bean
diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionService.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionService.java
index 02f81a0aa2..6008994be1 100644
--- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionService.java
+++ b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionService.java
@@ -33,7 +33,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.cloud.common.security.support.TokenUtils;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
import org.springframework.cloud.dataflow.core.AuditActionType;
import org.springframework.cloud.dataflow.core.AuditOperationType;
@@ -122,6 +122,8 @@ public class DefaultTaskExecutionService implements TaskExecutionService {
private final DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao;
+ private OAuth2TokenUtilsService oauth2TokenUtilsService;
+
private final Map> tasksBeingUpgraded = new ConcurrentHashMap<>();
/**
@@ -144,7 +146,8 @@ public DefaultTaskExecutionService(LauncherRepository launcherRepository,
TaskAppDeploymentRequestCreator taskAppDeploymentRequestCreator,
TaskExplorer taskExplorer,
DataflowTaskExecutionDao dataflowTaskExecutionDao,
- DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao) {
+ DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao,
+ OAuth2TokenUtilsService oauth2TokenUtilsService) {
Assert.notNull(launcherRepository, "launcherRepository must not be null");
Assert.notNull(auditRecordService, "auditRecordService must not be null");
Assert.notNull(taskExecutionInfoService, "taskExecutionInfoService must not be null");
@@ -157,6 +160,7 @@ public DefaultTaskExecutionService(LauncherRepository launcherRepository,
Assert.notNull(dataflowTaskExecutionDao, "dataflowTaskExecutionDao must not be null");
Assert.notNull(dataflowTaskExecutionMetadataDao, "dataflowTaskExecutionMetadataDao must not be null");
+ this.oauth2TokenUtilsService = oauth2TokenUtilsService;
this.launcherRepository = launcherRepository;
this.auditRecordService = auditRecordService;
this.taskRepository = taskRepository;
@@ -242,7 +246,6 @@ public long executeTask(String taskName, Map taskDeploymentPrope
logger.debug("Deleting %s and all related resources from the platform", taskName);
taskLauncher.destroy(taskName);
-
}
this.dataflowTaskExecutionMetadataDao.save(taskExecution, taskManifest);
@@ -307,8 +310,8 @@ private void handleAccessToken(List commandLineArgs, TaskExecutionInform
}
}
- if (!containsAccessToken && useUserAccessToken) {
- final String token = TokenUtils.getAccessToken();
+ if (!containsAccessToken && useUserAccessToken && oauth2TokenUtilsService != null) {
+ final String token = oauth2TokenUtilsService.getAccessTokenOfAuthenticatedUser();
if (token != null) {
taskExecutionInformation.getTaskDeploymentProperties().put(dataflowAccessTokenPropertyKey, token);
diff --git a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/ManualOAuthAuthenticationProvider.java b/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/ManualOAuthAuthenticationProvider.java
deleted file mode 100644
index c01aaca50c..0000000000
--- a/spring-cloud-dataflow-server-core/src/main/java/org/springframework/cloud/dataflow/server/service/impl/ManualOAuthAuthenticationProvider.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2016-2017 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.cloud.dataflow.server.service.impl;
-
-import org.slf4j.LoggerFactory;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
-import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.AuthenticationServiceException;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
-import org.springframework.security.oauth2.client.OAuth2RestTemplate;
-import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
-import org.springframework.security.oauth2.client.token.AccessTokenProvider;
-import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
-import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
-import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;
-import org.springframework.security.oauth2.common.OAuth2AccessToken;
-import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
-import org.springframework.security.oauth2.provider.OAuth2Authentication;
-import org.springframework.web.client.ResourceAccessException;
-
-/**
- * Provides a custom {@link AuthenticationProvider} that allows for authentication
- * (username and password) against an OAuth Server using a {@code password grant}.
- *
- * @author Gunnar Hillert
- */
-public class ManualOAuthAuthenticationProvider implements AuthenticationProvider {
-
- private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ManualOAuthAuthenticationProvider.class);
-
- @Autowired
- private OAuth2ClientProperties oAuth2ClientProperties;
-
- @Value("${security.oauth2.client.access-token-uri}")
- private String accessTokenUri;
-
- @Autowired
- private UserInfoTokenServices userInfoTokenServices;
-
- public AccessTokenProvider userAccessTokenProvider() {
- ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
- return accessTokenProvider;
- }
-
- @Override
- public Authentication authenticate(Authentication authentication) throws AuthenticationException {
- final String username = authentication.getName();
- final String password = authentication.getCredentials().toString();
-
- final ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
-
- resource.setUsername(username);
- resource.setPassword(password);
-
- resource.setAccessTokenUri(accessTokenUri);
- resource.setClientId(oAuth2ClientProperties.getClientId());
- resource.setClientSecret(oAuth2ClientProperties.getClientSecret());
- resource.setGrantType("password");
-
- final OAuth2RestTemplate template = new OAuth2RestTemplate(resource,
- new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
- template.setAccessTokenProvider(userAccessTokenProvider());
-
- final OAuth2AccessToken accessToken;
- try {
- logger.warn("Authenticating user '{}' using accessTokenUri '{}'.", username, accessTokenUri);
- accessToken = template.getAccessToken();
- }
- catch (OAuth2AccessDeniedException e) {
- if (e.getCause() instanceof ResourceAccessException) {
- final String errorMessage = String.format(
- "While authenticating user '%s': " + "Unable to access accessTokenUri '%s'.", username,
- accessTokenUri);
- logger.error(errorMessage + " Error message: {}.", e.getCause().getMessage());
- throw new AuthenticationServiceException(errorMessage, e);
- }
- throw new BadCredentialsException(String.format("Access denied for user '%s'.", username), e);
- }
- catch (OAuth2Exception e) {
- throw new AuthenticationServiceException(
- String.format("Unable to perform OAuth authentication for user '%s'.", username), e);
- }
-
- final OAuth2Authentication auth2Authentication = userInfoTokenServices
- .loadAuthentication(accessToken.getValue());
- return auth2Authentication;
- }
-
- @Override
- public boolean supports(Class> authentication) {
- return authentication.equals(UsernamePasswordAuthenticationToken.class);
- }
-}
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfigurationTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfigurationTests.java
index 44f8afa759..56fc4538b7 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfigurationTests.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DataFlowServerConfigurationTests.java
@@ -33,6 +33,7 @@
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.server.EnableDataFlowServer;
import org.springframework.cloud.dataflow.server.config.features.SchedulerConfiguration;
import org.springframework.cloud.dataflow.server.config.web.WebConfiguration;
@@ -63,6 +64,7 @@
/**
* @author Glenn Renfro
* @author Ilayaperumal Gopinathan
+ * @author Gunnar Hillert
*/
public class DataFlowServerConfigurationTests {
@@ -191,5 +193,10 @@ public Scheduler scheduler() {
public StreamValidationService streamValidationService() {
return mock(StreamValidationService.class);
}
+
+ @Bean
+ public OAuth2TokenUtilsService oauth2TokenUtilsService() {
+ return mock(OAuth2TokenUtilsService.class);
+ }
}
}
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DefaultEnvironmentPostProcessorTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DefaultEnvironmentPostProcessorTests.java
index 9e3832468c..93a4506a06 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DefaultEnvironmentPostProcessorTests.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/config/DefaultEnvironmentPostProcessorTests.java
@@ -22,6 +22,7 @@
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.server.EnableDataFlowServer;
import org.springframework.cloud.dataflow.server.service.SchedulerService;
import org.springframework.cloud.dataflow.server.service.TaskExecutionService;
@@ -115,5 +116,10 @@ public SchedulerService schedulerService() {
public Scheduler scheduler() {
return mock(Scheduler.class);
}
+
+ @Bean
+ public OAuth2TokenUtilsService oauth2TokenUtilsService() {
+ return mock(OAuth2TokenUtilsService.class);
+ }
}
}
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java
index 1dddb9e678..40eec67161 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/JobDependencies.java
@@ -39,6 +39,7 @@
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.audit.repository.AuditRecordRepository;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
import org.springframework.cloud.dataflow.audit.service.DefaultAuditRecordService;
@@ -265,14 +266,15 @@ public TaskExecutionService taskService(LauncherRepository launcherRepository,
TaskExecutionCreationService taskExecutionRepositoryService,
TaskAppDeploymentRequestCreator taskAppDeploymentRequestCreator,
TaskExplorer taskExplorer, DataflowTaskExecutionDao dataflowTaskExecutionDao,
- DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao) {
+ DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao,
+ OAuth2TokenUtilsService oauth2TokenUtilsService) {
return new DefaultTaskExecutionService(
launcherRepository, auditRecordService,
taskRepository,
taskExecutionInfoService, taskDeploymentRepository,
taskExecutionRepositoryService, taskAppDeploymentRequestCreator,
taskExplorer, dataflowTaskExecutionDao,
- dataflowTaskExecutionMetadataDao);
+ dataflowTaskExecutionMetadataDao, oauth2TokenUtilsService);
}
@Bean
@@ -440,4 +442,8 @@ public ScheduleInfo getSchedule(String scheduleName) {
};
}
+ @Bean
+ public OAuth2TokenUtilsService oauth2TokenUtilsService() {
+ return mock(OAuth2TokenUtilsService.class);
+ }
}
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TaskServiceDependencies.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TaskServiceDependencies.java
index 468ae9aab6..6e38f91cf3 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TaskServiceDependencies.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TaskServiceDependencies.java
@@ -34,6 +34,7 @@
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
import org.springframework.cloud.dataflow.audit.service.DefaultAuditRecordService;
import org.springframework.cloud.dataflow.completion.CompletionConfiguration;
@@ -280,12 +281,14 @@ public TaskExecutionService defaultTaskService(LauncherRepository launcherReposi
TaskExecutionCreationService taskExecutionRepositoryService,
TaskAppDeploymentRequestCreator taskAppDeploymentRequestCreator,
TaskExplorer taskExplorer, DataflowTaskExecutionDao dataflowTaskExecutionDao,
- DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao) {
+ DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao,
+ OAuth2TokenUtilsService oauth2TokenUtilsService) {
return new DefaultTaskExecutionService(
launcherRepository, auditRecordService, taskRepository,
taskExecutionInfoService, taskDeploymentRepository,
taskExecutionRepositoryService, taskAppDeploymentRequestCreator,
- taskExplorer, dataflowTaskExecutionDao, dataflowTaskExecutionMetadataDao);
+ taskExplorer, dataflowTaskExecutionDao, dataflowTaskExecutionMetadataDao,
+ oauth2TokenUtilsService);
}
@Bean
@@ -328,4 +331,11 @@ public TaskPlatform taskPlatform(Scheduler scheduler) {
public Scheduler scheduler() {
return new SimpleTestScheduler();
}
+
+ @Bean
+ public OAuth2TokenUtilsService oauth2TokenUtilsService() {
+ final OAuth2TokenUtilsService oauth2TokenUtilsService = mock(OAuth2TokenUtilsService.class);
+ when(oauth2TokenUtilsService.getAccessTokenOfAuthenticatedUser()).thenReturn("foo-bar-123-token");
+ return oauth2TokenUtilsService;
+ }
}
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java
index 40184b9e5e..3a6b07ee4d 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/configuration/TestDependencies.java
@@ -42,6 +42,7 @@
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.common.security.support.SecurityStateBean;
import org.springframework.cloud.dataflow.audit.repository.AuditRecordRepository;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
@@ -510,12 +511,14 @@ public TaskExecutionService taskService(LauncherRepository launcherRepository,
TaskExecutionCreationService taskExecutionRepositoryService,
TaskAppDeploymentRequestCreator taskAppDeploymentRequestCreator,
TaskExplorer taskExplorer, DataflowTaskExecutionDao dataflowTaskExecutionDao,
- DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao) {
+ DataflowTaskExecutionMetadataDao dataflowTaskExecutionMetadataDao,
+ OAuth2TokenUtilsService oauth2TokenUtilsService) {
return new DefaultTaskExecutionService(
launcherRepository, auditRecordService, taskRepository,
taskExecutionInfoService, taskDeploymentRepository,
taskExecutionRepositoryService, taskAppDeploymentRequestCreator,
- taskExplorer, dataflowTaskExecutionDao, dataflowTaskExecutionMetadataDao);
+ taskExplorer, dataflowTaskExecutionDao, dataflowTaskExecutionMetadataDao,
+ oauth2TokenUtilsService);
}
@Bean
@@ -624,4 +627,9 @@ public JobStepExecutionProgressController jobStepExecutionProgressController() {
public JobInstanceController jobInstanceController() {
return mock(JobInstanceController.class);
}
+
+ @Bean
+ public OAuth2TokenUtilsService oauth2TokenUtilsService() {
+ return mock(OAuth2TokenUtilsService.class);
+ }
}
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTests.java
index 934e7f8177..95393753c9 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTests.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTests.java
@@ -45,6 +45,7 @@
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.system.OutputCaptureRule;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
import org.springframework.cloud.dataflow.core.AppRegistration;
import org.springframework.cloud.dataflow.core.ApplicationType;
@@ -83,9 +84,6 @@
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.FileUrlResource;
import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.provider.OAuth2Authentication;
-import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@@ -659,7 +657,9 @@ public void executeTaskWithNullDefinitionTest() {
launcherRepository, auditRecordService, taskRepository,
taskExecutionInfoService, mock(TaskDeploymentRepository.class),
taskExecutionRepositoryService, taskAppDeploymentRequestCreator,
- this.taskExplorer, this.dataflowTaskExecutionDao, this.dataflowTaskExecutionMetadataDao);
+ this.taskExplorer, this.dataflowTaskExecutionDao, this.dataflowTaskExecutionMetadataDao,
+ mock(OAuth2TokenUtilsService.class));
+
try {
taskExecutionService.executeTask(TASK_NAME_ORIG, new HashMap<>(), new LinkedList<>());
}
@@ -871,12 +871,6 @@ public void executeComposedTaskWithAccessTokenOverrideAsArgument() {
private Map prepareEnvironmentForTokenTests() {
- final OAuth2Authentication oAuth2Authentication = mock(OAuth2Authentication.class);
- final OAuth2AuthenticationDetails oAuth2AuthenticationDetails = mock(OAuth2AuthenticationDetails.class);
- when(oAuth2AuthenticationDetails.getTokenValue()).thenReturn("foo-bar-123-token");
- when(oAuth2Authentication.getDetails()).thenReturn(oAuth2AuthenticationDetails);
- SecurityContextHolder.getContext().setAuthentication(oAuth2Authentication);
-
taskSaveService.saveTaskDefinition(new TaskDefinition("seqTask", "AAA && BBB"));
when(taskLauncher.launch(any())).thenReturn("0");
when(appRegistry.appExist(anyString(), any(ApplicationType.class))).thenReturn(true);
diff --git a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTransactionTests.java b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTransactionTests.java
index 9988519ed9..87ec56f162 100644
--- a/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTransactionTests.java
+++ b/spring-cloud-dataflow-server-core/src/test/java/org/springframework/cloud/dataflow/server/service/impl/DefaultTaskExecutionServiceTransactionTests.java
@@ -35,6 +35,7 @@
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.common.security.support.OAuth2TokenUtilsService;
import org.springframework.cloud.dataflow.audit.service.AuditRecordService;
import org.springframework.cloud.dataflow.core.AppRegistration;
import org.springframework.cloud.dataflow.core.ApplicationType;
@@ -74,6 +75,7 @@
/**
* @author Glenn Renfro
+ * @author Gunnar Hillert
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { TaskServiceDependencies.class }, properties = {
@@ -139,8 +141,8 @@ public void setupMocks() {
launcherRepository, auditRecordService, taskRepository,
taskExecutionInfoService, mock(TaskDeploymentRepository.class),
taskExecutionRepositoryService, taskAppDeploymentRequestCreator,
- this.taskExplorer, this.dataflowTaskExecutionDao, this.dataflowTaskExecutionMetadataDao);
-
+ this.taskExplorer, this.dataflowTaskExecutionDao, this.dataflowTaskExecutionMetadataDao,
+ mock(OAuth2TokenUtilsService.class));
}
@Test
diff --git a/spring-cloud-dataflow-server/pom.xml b/spring-cloud-dataflow-server/pom.xml
index c847079598..54e7268910 100644
--- a/spring-cloud-dataflow-server/pom.xml
+++ b/spring-cloud-dataflow-server/pom.xml
@@ -19,6 +19,11 @@
+
+ io.projectreactor
+ reactor-core
+ 3.3.0.RELEASE
+
org.springframework.cloud
spring-cloud-starter-dataflow-server
diff --git a/spring-cloud-starter-dataflow-server/pom.xml b/spring-cloud-starter-dataflow-server/pom.xml
index 31482ec10b..83918761a0 100644
--- a/spring-cloud-starter-dataflow-server/pom.xml
+++ b/spring-cloud-starter-dataflow-server/pom.xml
@@ -46,6 +46,12 @@
spring-cloud-dataflow-rest-client
test
+
+ org.springframework.security.oauth
+ spring-security-oauth2
+ ${spring-security-oauth2.version}
+ test
+
diff --git a/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithOAuth2Tests.java b/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithOAuth2Tests.java
index a416d49927..36ed3adfeb 100644
--- a/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithOAuth2Tests.java
+++ b/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithOAuth2Tests.java
@@ -264,11 +264,9 @@ public void testAccessSecurityInfoUrlWithOAuth2AccessToken2TimesAndLogout() thro
assertTrue(Boolean.valueOf(oAuthServerResponse));
- // At this point the Token is still cached by the Data Flow Server, and therefore a positive response is expected
-
localDataflowResource.getMockMvc()
.perform(get("/security/info").header("Authorization", "bearer " + accessTokenAsString)).andDo(print())
- .andExpect(status().isOk());
+ .andExpect(status().isUnauthorized());
localDataflowResource.getMockMvc()
.perform(get("/logout").header("Authorization", "bearer " + accessTokenAsString)).andDo(print())
@@ -276,7 +274,7 @@ public void testAccessSecurityInfoUrlWithOAuth2AccessToken2TimesAndLogout() thro
localDataflowResource.getMockMvc()
.perform(get("/security/info").header("Authorization", "bearer " + accessTokenAsString)).andDo(print())
- .andExpect(status().isOk()); //FIXME
+ .andExpect(status().isUnauthorized());
}
diff --git a/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithUsersFileTests.java b/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithUsersFileTests.java
index b0f4be7abd..a408225708 100644
--- a/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithUsersFileTests.java
+++ b/spring-cloud-starter-dataflow-server/src/test/java/org/springframework/cloud/dataflow/server/single/security/LocalServerSecurityWithUsersFileTests.java
@@ -724,5 +724,11 @@ public String getUsername() {
public String getPassword() {
return password;
}
+
+ @Override
+ public String toString() {
+ return String.format("UserCredentials: %s/%s.", this.username, this.password);
+ }
+
}
}
diff --git a/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/oauthConfig.yml b/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/oauthConfig.yml
index 999b71623e..4c372f2c60 100644
--- a/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/oauthConfig.yml
+++ b/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/oauthConfig.yml
@@ -11,24 +11,40 @@ spring:
dataflow:
security:
authorization:
- map-oauth-scopes: true
- role-mappings:
- ROLE_VIEW: dataflow.view
- ROLE_CREATE: dataflow.create
- ROLE_MANAGE: dataflow.manage
- ROLE_DEPLOY: dataflow.create
- ROLE_DESTROY: dataflow.create
- ROLE_MODIFY: dataflow.create
- ROLE_SCHEDULE: dataflow.create
-security:
- oauth2:
- client:
- client-id: myclient
- client-secret: mysecret
- access-token-uri: http://127.0.0.1:${oauth2.port}/oauth/token
- user-authorization-uri: http://127.0.0.1:${oauth2.port}/oauth/authorize
- resource:
- user-info-uri: http://127.0.0.1:${oauth2.port}/me
- token-info-uri: http://127.0.0.1:${oauth2.port}/oauth/check_token
- authorization:
- check-token-access: isAuthenticated()
+ provider-role-mappings:
+ uaa:
+ map-oauth-scopes: true
+ role-mappings:
+ ROLE_VIEW: dataflow.view
+ ROLE_CREATE: dataflow.create
+ ROLE_MANAGE: dataflow.manage
+ ROLE_DEPLOY: dataflow.create
+ ROLE_DESTROY: dataflow.create
+ ROLE_MODIFY: dataflow.create
+ ROLE_SCHEDULE: dataflow.create
+ security:
+ oauth2:
+ client:
+ registration:
+ uaa:
+ redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
+ authorization-grant-type: authorization_code
+ client-id: myclient
+ client-secret: mysecret
+ access-token-uri: http://127.0.0.1:${oauth2.port}/oauth/token
+ user-authorization-uri: http://127.0.0.1:${oauth2.port}/oauth/authorize
+ provider:
+ uaa:
+ authorization-uri: http://127.0.0.1:${oauth2.port}/oauth/authorize
+ user-info-uri: http://127.0.0.1:${oauth2.port}/me
+ token-uri: http://127.0.0.1:${oauth2.port}/oauth/token
+ resourceserver:
+ opaquetoken:
+ introspection-uri: http://127.0.0.1:${oauth2.port}/oauth/check_token
+ client-id: myclient
+ client-secret: mysecret
+ authorization:
+ check-token-access: isAuthenticated()
+logging:
+ level:
+ org.springframework.security: WARN
diff --git a/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/support/oauth2testserver/oauth2TestServerConfig.yml b/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/support/oauth2testserver/oauth2TestServerConfig.yml
index d0abe19067..c7d439893b 100644
--- a/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/support/oauth2testserver/oauth2TestServerConfig.yml
+++ b/spring-cloud-starter-dataflow-server/src/test/resources/org/springframework/cloud/dataflow/server/single/security/support/oauth2testserver/oauth2TestServerConfig.yml
@@ -8,7 +8,7 @@ security:
client-secret: "{noop}mysecret"
scope: dataflow.view,dataflow.manage,dataflow.create
registered-redirect-uri:
- - http://localhost:9393/login
+ - http://localhost:${dataflow.port}/login/oauth2/code/uaa
auto-approve-scopes: '.*'
authorized-grant-types:
- authorization_code