Sync docs from v1.2.2.RELEASE to gh-pages

This commit is contained in:
buildmaster
2018-01-16 14:38:51 +00:00
parent b098225816
commit ff5df0a284
48 changed files with 2278 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

View File

@@ -0,0 +1,330 @@
#!/bin/bash -x
set -e
# Set default props like MAVEN_PATH, ROOT_FOLDER etc.
function set_default_props() {
# The script should be executed from the root folder
ROOT_FOLDER=`pwd`
echo "Current folder is ${ROOT_FOLDER}"
if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then
echo "You're not in the root folder of the project!"
exit 1
fi
# Prop that will let commit the changes
COMMIT_CHANGES="no"
MAVEN_PATH=${MAVEN_PATH:-}
echo "Path to Maven is [${MAVEN_PATH}]"
REPO_NAME=${PWD##*/}
echo "Repo name is [${REPO_NAME}]"
SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git}
echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}"
}
# Check if gh-pages exists and docs have been built
function check_if_anything_to_sync() {
git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'`
if ! (git remote set-branches --add origin gh-pages && git fetch -q); then
echo "No gh-pages, so not syncing"
exit 0
fi
if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then
echo "No gh-pages sources in docs/target/generated-docs, so not syncing"
exit 0
fi
}
function retrieve_current_branch() {
# Code getting the name of the current branch. For master we want to publish as we did until now
# http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
if [[ -z "${CURRENT_BRANCH}" ]] ; then
CURRENT_BRANCH=$(git symbolic-ref -q HEAD)
CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/}
CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD}
fi
echo "Current branch is [${CURRENT_BRANCH}]"
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
}
# Switches to the provided value of the release version. We always prefix it with `v`
function switch_to_tag() {
git checkout v${VERSION}
}
# Build the docs if switch is on
function build_docs_if_applicable() {
if [[ "${BUILD}" == "yes" ]] ; then
./mvnw clean install -P docs -pl docs -DskipTests
fi
}
# Get the name of the `docs.main` property
# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile
function retrieve_doc_properties() {
MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args='${docs.main}' \
--non-recursive \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec)
echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]"
WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"}
WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \
-Dexec.executable="echo" \
-Dexec.args="\${${WHITELIST_PROPERTY}}" \
org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
-P docs \
-pl docs)
echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]"
}
# Stash any outstanding changes
function stash_changes() {
git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1")
if [ "$dirty" != "0" ]; then git stash; fi
}
# Switch to gh-pages branch to sync it with current branch
function add_docs_from_target() {
local DESTINATION_REPO_FOLDER
if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then
DESTINATION_REPO_FOLDER=${ROOT_FOLDER}
elif [[ "${CLONE}" == "yes" ]]; then
mkdir -p ${ROOT_FOLDER}/target
local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static
if [[ ! -e "${clonedStatic}/.git" ]]; then
echo "Cloning Spring Cloud Static to target"
git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages
else
echo "Spring Cloud Static already cloned - will pull changes"
cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages
fi
DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
else
if [[ ! -e "${DESTINATION}/.git" ]]; then
echo "[${DESTINATION}] is not a git repository"
exit 1
fi
DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME}
mkdir -p ${DESTINATION_REPO_FOLDER}
echo "Destination was provided [${DESTINATION}]"
fi
cd ${DESTINATION_REPO_FOLDER}
git checkout gh-pages
git pull origin gh-pages
# Add git branches
###################################################################
if [[ -z "${VERSION}" ]] ; then
copy_docs_for_current_version
else
copy_docs_for_provided_version
fi
commit_changes_if_applicable
}
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
echo -e "Current branch is master - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
cp -rf $f ${ROOT_FOLDER}/
git add -A ${ROOT_FOLDER}/$file
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Current branch is [${CURRENT_BRANCH}]"
# http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin
if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then
mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH}
echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html
else
cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}
git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file
fi
fi
done
COMMIT_CHANGES="yes"
else
echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in
[docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch."
fi
fi
}
# Copies the docs by using the explicitly provided version
function copy_docs_for_provided_version() {
local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION}
mkdir -p ${FOLDER}
echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder"
for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do
file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*}
copy_docs_for_branch ${file} ${FOLDER}
done
COMMIT_CHANGES="yes"
CURRENT_BRANCH="v${VERSION}"
}
# Copies the docs from target to the provided destination
# Params:
# $1 - file from target
# $2 - destination to which copy the files
function copy_docs_for_branch() {
local file=$1
local destination=$2
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then
# Not ignored...
# We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html
if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then
# We don't want to copy the spring-cloud-sleuth.html
# we want it to be converted to index.html
cp -rf $f ${destination}/index.html
git add -A ${destination}/index.html
else
cp -rf $f ${destination}
git add -A ${destination}/$file
fi
fi
}
function commit_changes_if_applicable() {
if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then
COMMIT_SUCCESSFUL="no"
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
git push origin gh-pages
fi
fi
}
# Switch back to the previous branch and exit block
function checkout_previous_branch() {
# If -version was provided we need to come back to root project
cd ${ROOT_FOLDER}
git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script"
if [ "$dirty" != "0" ]; then git stash pop; fi
exit 0
}
# Assert if properties have been properly passed
function assert_properties() {
echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]"
if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi
if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi
if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi
}
# Prints the usage
function print_usage() {
cat <<EOF
The idea of this script is to update gh-pages branch with the generated docs. Without any options
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
- for master branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is whitelisted) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
with that version number will be created in the gh-pages branch. WARNING! No whitelist verification will take place
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will
switch to gh-pages of that repo and copy the generated docs to `docs/<project-name>/<version>`
USAGE:
You can use the following options:
-v|--version - the script will apply the whole procedure for a particular library version
-d|--destination - the root of destination folder where the docs should be copied. You have to use the full path.
E.g. point to spring-cloud-static folder. Can't be used with (-c)
-b|--build - will run the standard build process after checking out the branch
-c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination.
Obviously can't be used with (-d)
EOF
}
# ==========================================
# ____ ____ _____ _____ _____ _______
# / ____|/ ____| __ \|_ _| __ \__ __|
# | (___ | | | |__) | | | | |__) | | |
# \___ \| | | _ / | | | ___/ | |
# ____) | |____| | \ \ _| |_| | | |
# |_____/ \_____|_| \_\_____|_| |_|
#
# ==========================================
while [[ $# > 0 ]]
do
key="$1"
case ${key} in
-v|--version)
VERSION="$2"
shift # past argument
;;
-d|--destination)
DESTINATION="$2"
shift # past argument
;;
-b|--build)
BUILD="yes"
;;
-c|--clone)
CLONE="yes"
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Invalid option: [$1]"
print_usage
exit 1
;;
esac
shift # past argument or value
done
assert_properties
set_default_props
check_if_anything_to_sync
if [[ -z "${VERSION}" ]] ; then
retrieve_current_branch
else
switch_to_tag
fi
build_docs_if_applicable
retrieve_doc_properties
stash_changes
add_docs_from_target
checkout_previous_branch

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.5">
<title>spring-cloud-security</title>
<link rel="stylesheet" href="css/manual-singlepage.css">
<style>
.hidden {
display: none;
}
.switch {
border-width: 1px 1px 0 1px;
border-style: solid;
border-color: #7a2518;
display: inline-block;
}
.switch--item {
padding: 10px;
background-color: #ffffff;
color: #7a2518;
display: inline-block;
cursor: pointer;
}
.switch--item.selected {
background-color: #7a2519;
color: #ffffff;
}
</style>
<script src="http://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
$('.primary').each(function() {
primary = $(this);
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
primary.children('.title').remove();
});
$('.secondary').each(function(idx, node) {
secondary = $(node);
primary = findPrimary(secondary);
switchItem = createSwitchItem(secondary, primary.children('.switch'));
switchItem.content.addClass('hidden');
findPrimary(secondary).append(switchItem.content);
secondary.remove();
});
}
function createBlockSwitch(primary) {
blockSwitch = $('<div class="switch"></div>');
primary.prepend(blockSwitch);
return blockSwitch;
}
function findPrimary(secondary) {
candidate = secondary.prev();
while (!candidate.is('.primary')) {
candidate = candidate.prev();
}
return candidate;
}
function createSwitchItem(block, blockSwitch) {
blockName = block.children('.title').text();
content = block.children('.content').first().append(block.next('.colist'));
item = $('<div class="switch--item">' + blockName + '</div>');
item.on('click', '', content, function(e) {
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
e.data.siblings('.content').addClass('hidden');
e.data.removeClass('hidden');
});
blockSwitch.append(item);
return {'item': item, 'content': content};
}
$(addBlockSwitches);
</script>
</head>
<body class="article">
<div id="header">
<h1>spring-cloud-security</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>1.2.2.RELEASE</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pick_the_documentation_option">Pick The Documentation Option</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="single/spring-cloud-security.html">Single HTML</a></p>
</li>
<li>
<p><a href="multi/multi_spring-cloud-security.html">Multi HTML</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,17 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>3.&nbsp;Configuring Authentication Downstream of a Zuul Proxy</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="up" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="prev" href="multi__more_detail.html" title="2.&nbsp;More Detail"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3.&nbsp;Configuring Authentication Downstream of a Zuul Proxy</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__more_detail.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;</td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_configuring_authentication_downstream_of_a_zuul_proxy" href="#_configuring_authentication_downstream_of_a_zuul_proxy"></a>3.&nbsp;Configuring Authentication Downstream of a Zuul Proxy</h1></div></div></div><p>You can control the authorization behaviour downstream of an
<code class="literal">@EnableZuulProxy</code> through the <code class="literal">proxy.auth.*</code> settings. Example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">proxy</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> auth</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> routes</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> customers</span>: oauth2
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> stores</span>: passthru
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> recommendations</span>: none</pre><p>
</p><p>In this example the "customers" service gets an OAuth2 token relay,
the "stores" service gets a passthrough (the authorization header is
just passed downstream), and the "recommendations" service has its
authorization header removed. The default behaviour is to do a token
relay if there is a token available, and passthru otherwise.</p><p>See
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/ProxyAuthenticationProperties" target="_top">
ProxyAuthenticationProperties</a> for full details.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__more_detail.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;</td></tr><tr><td width="40%" align="left" valign="top">2.&nbsp;More Detail&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-security.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,84 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>2.&nbsp;More Detail</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="up" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="prev" href="multi__quickstart.html" title="1.&nbsp;Quickstart"><link rel="next" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html" title="3.&nbsp;Configuring Authentication Downstream of a Zuul Proxy"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">2.&nbsp;More Detail</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__quickstart.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_more_detail" href="#_more_detail"></a>2.&nbsp;More Detail</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_single_sign_on" href="#_single_sign_on"></a>2.1&nbsp;Single Sign On</h2></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>All of the OAuth2 SSO and resource server features moved to Spring Boot
in version 1.3. You can find documentation in the
<a class="link" href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/" target="_top">Spring Boot user guide</a>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_token_relay" href="#_token_relay"></a>2.2&nbsp;Token Relay</h2></div></div></div><p>A Token Relay is where an OAuth2 consumer acts as a Client and
forwards the incoming token to outgoing resource requests. The
consumer can be a pure Client (like an SSO application) or a Resource
Server.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay" href="#_client_token_relay"></a>2.2.1&nbsp;Client Token Relay</h3></div></div></div><p>If your app is a user facing OAuth2 client (i.e. has declared
<code class="literal">@EnableOAuth2Sso</code> or <code class="literal">@EnableOAuth2Client</code>) then it has an
<code class="literal">OAuth2ClientContext</code> in request scope from Spring Boot. You can
create your own <code class="literal">OAuth2RestTemplate</code> from this context and an
autowired <code class="literal">OAuth2ProtectedResourceDetails</code>, and then the context will
always forward the access token downstream, also refreshing the access
token automatically if it expires. (These are features of Spring
Security and Spring Boot.)</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Boot (1.4.1) does not create an
<code class="literal">OAuth2ProtectedResourceDetails</code> automatically if you are using
<code class="literal">client_credentials</code> tokens. In that case you need to create your own
<code class="literal">ClientCredentialsResourceDetails</code> and configure it with
<code class="literal">@ConfigurationProperties("security.oauth2.client")</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay_in_zuul_proxy" href="#_client_token_relay_in_zuul_proxy"></a>2.2.2&nbsp;Client Token Relay in Zuul Proxy</h3></div></div></div><p>If your app also has a
<a class="link" href="http://cloud.spring.io/spring-cloud.html#netflix-zuul-reverse-proxy" target="_top">Spring
Cloud Zuul</a> embedded reverse proxy (using <code class="literal">@EnableZuulProxy</code>) then you
can ask it to forward OAuth2 access tokens downstream to the services
it is proxying. Thus the SSO app above can be enhanced simply like
this:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableOAuth2Sso</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableZuulProxy</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
}</pre><p>
</p><p>and it will (in addition to logging the user in and grabbing a token)
pass the authentication token downstream to the <code class="literal">/proxy/*</code>
services. If those services are implemented with
<code class="literal">@EnableResourceServer</code> then they will get a valid token in the
correct header.</p><p>How does it work? The <code class="literal">@EnableOAuth2Sso</code> annotation pulls in
<code class="literal">spring-cloud-starter-security</code> (which you could do manually in a
traditional app), and that in turn triggers some autoconfiguration for
a <code class="literal">ZuulFilter</code>, which itself is activated because Zuul is on the
classpath (via <code class="literal">@EnableZuulProxy</code>). The
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/OAuth2TokenRelayFilter.java" target="_top">filter</a>
just extracts an access token from the currently authenticated user,
and puts it in a request header for the downstream requests.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resource_server_token_relay" href="#_resource_server_token_relay"></a>2.2.3&nbsp;Resource Server Token Relay</h3></div></div></div><p>If your app has <code class="literal">@EnableResourceServer</code> you might want to relay the
incoming token downstream to other services. If you use a
<code class="literal">RestTemplate</code> to contact the downstream services then this is just a
matter of how to create the template with the right context.</p><p>If your service uses <code class="literal">UserInfoTokenServices</code> to authenticate incoming
tokens (i.e. it is using the <code class="literal">security.oauth2.user-info-uri</code>
configuration), then you can simply create an <code class="literal">OAuth2RestTemplate</code>
using an autowired <code class="literal">OAuth2ClientContext</code> (it will be populated by the
authentication process before it hits the backend code). Equivalently
(with Spring Boot 1.4), you could inject a
<code class="literal">UserInfoRestTemplateFactory</code> and grab its <code class="literal">OAuth2RestTemplate</code> in
your configuration. For example:</p><p><b>MyConfiguration.java.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory.getUserInfoRestTemplate();
}</pre><p>
</p><p>This rest template will then have the same <code class="literal">OAuth2ClientContext</code>
(request-scoped) that is used by the authentication filter, so you can
use it to send requests with the same access token.</p><p>If your app is not using <code class="literal">UserInfoTokenServices</code> but is still a client
(i.e. it declares <code class="literal">@EnableOAuth2Client</code> or <code class="literal">@EnableOAuth2Sso</code>), then
with Spring Security Cloud any <code class="literal">OAuth2RestOperations</code> that the user
creates from an <code class="literal">@Autowired</code> <code class="literal">@OAuth2Context</code> will also forward
tokens. This feature is implemented by default as an MVC handler
interceptor, so it only works in Spring MVC. If you are not using MVC
you could use a custom filter or AOP interceptor wrapping an
<code class="literal">AccessTokenContextRelay</code> to provide the same feature.</p><p>Here&#8217;s a basic
example showing the use of an autowired rest template created
elsewhere ("foo.com" is a Resource Server accepting the same tokens as
the surrounding app):</p><p><b>MyController.java.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> OAuth2RestOperations restTemplate;
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/relay")</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String relay() {
ResponseEntity&lt;String&gt; response =
restTemplate.getForEntity(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://foo.com/bar"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Success! ("</span> + response.getBody() + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")"</span>;
}</pre><p>
</p><p>If you don&#8217;t want to forward tokens (and that is a valid
choice, since you might want to act as yourself, rather than the
client that sent you the token), then you only need to create your own
<code class="literal">OAuth2Context</code> instead of autowiring the default one.</p><p>Feign clients will also pick up an interceptor that uses the
<code class="literal">OAuth2ClientContext</code> if it is available, so they should also do a
token relay anywhere where a <code class="literal">RestTemplate</code> would.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__quickstart.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">1.&nbsp;Quickstart&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-security.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;3.&nbsp;Configuring Authentication Downstream of a Zuul Proxy</td></tr></table></div></body></html>

View File

@@ -0,0 +1,72 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>1.&nbsp;Quickstart</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="up" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="prev" href="multi_pr01.html" title=""><link rel="next" href="multi__more_detail.html" title="2.&nbsp;More Detail"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">1.&nbsp;Quickstart</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__more_detail.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_quickstart" href="#_quickstart"></a>1.&nbsp;Quickstart</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_oauth2_single_sign_on" href="#_oauth2_single_sign_on"></a>1.1&nbsp;OAuth2 Single Sign On</h2></div></div></div><p>Here&#8217;s a Spring Cloud "Hello World" app with HTTP Basic
authentication and a single user account:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Grab('spring-boot-starter-security')</span></em>
<em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
String home() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello World'</span>
}
}</pre><p>
</p><p>You can run it with <code class="literal">spring run app.groovy</code> and watch the logs for the password (username is "user"). So far this is just the default for a Spring Boot app.</p><p>Here&#8217;s a Spring Cloud app with OAuth2 SSO:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableOAuth2Sso</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
String home() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello World'</span>
}
}</pre><p>
</p><p>Spot the difference? This app will actually behave exactly the same as
the previous one, because it doesn&#8217;t know it&#8217;s OAuth2 credentals
yet.</p><p>You can register an app in github quite easily, so try that if you
want a production app on your own domain. If you are happy to test on
localhost:8080, then set up these properties in your application
configuration:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">security</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> oauth2</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> client</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> clientId</span>: bd1c0a783ccdd1c9b9e4
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> clientSecret</span>: <span class="hl-number">1</span>a9030fbca47a5b2c28e92f19050bb77824b5ad1
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> accessTokenUri</span>: https://github.com/login/oauth/access_token
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> userAuthorizationUri</span>: https://github.com/login/oauth/authorize
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> clientAuthenticationScheme</span>: form
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> resource</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> userInfoUri</span>: https://api.github.com/user
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> preferTokenInfo</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span></pre><p>
</p><p>run the app above and it will redirect to github for authorization. If
you are already signed into github you won&#8217;t even notice that it has
authenticated. These credentials will only work if your app is
running on port 8080.</p><p>To limit the scope that the client asks for when it obtains an access token
you can set <code class="literal">security.oauth2.client.scope</code> (comma separated or an array in YAML). By
default the scope is empty and it is up to to Authorization Server to
decide what the defaults should be, usually depending on the settings in
the client registration that it holds.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The examples above are all Groovy scripts. If you want to write the
same code in Java (or Groovy) you need to add Spring Security OAuth2
to the classpath (e.g. see the
<a class="link" href="https://github.com/spring-cloud-samples/sso" target="_top">sample here</a>).</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_oauth2_protected_resource" href="#_oauth2_protected_resource"></a>1.2&nbsp;OAuth2 Protected Resource</h2></div></div></div><p>You want to protect an API resource with an OAuth2 token? Here&#8217;s a
simple example (paired with the client above):</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Grab('spring-cloud-starter-security')</span></em>
<em><span class="hl-annotation" style="color: gray">@RestController</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableResourceServer</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
def home() {
[message: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello World'</span>]
}
}</pre><p>
</p><p>and</p><p><b>application.yml.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">security</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> oauth2</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> resource</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> userInfoUri</span>: https://api.github.com/user
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> preferTokenInfo</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span></pre><p>
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_pr01.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__more_detail.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-security.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;2.&nbsp;More Detail</td></tr></table></div></body></html>

View File

@@ -0,0 +1,11 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title></title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="up" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="prev" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="next" href="multi__quickstart.html" title="1.&nbsp;Quickstart"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center"></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi_spring-cloud-security.html">Prev</a>&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__quickstart.html">Next</a></td></tr></table><hr></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>Spring Cloud Security offers a set of primitives for building secure
applications and services with minimum fuss. A declarative model which
can be heavily configured externally (or centrally) lends itself to
the implementation of large systems of co-operating, remote components,
usually with a central indentity management service. It is also extremely
easy to use in a service platform like Cloud Foundry. Building on
Spring Boot and Spring Security OAuth2 we can quickly create systems that
implement common patterns like single sign on, token relay and token
exchange.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/asciidoc" target="_top">github</a>.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi_spring-cloud-security.html">Prev</a>&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__quickstart.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Spring Cloud Security&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-security.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;1.&nbsp;Quickstart</td></tr></table></div></body></html>

View File

@@ -0,0 +1,3 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Security</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud-security.html" title="Spring Cloud Security"><link rel="next" href="multi_pr01.html" title=""></head><body class="firstpage" bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Spring Cloud Security</th></tr><tr><td width="20%" align="left">&nbsp;</td><th width="60%" align="center">&nbsp;</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr></table><hr></div><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Security</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="multi_pr01.html"></a></span></dt><dt><span class="chapter"><a href="multi__quickstart.html">1. Quickstart</a></span></dt><dd><dl><dt><span class="section"><a href="multi__quickstart.html#_oauth2_single_sign_on">1.1. OAuth2 Single Sign On</a></span></dt><dt><span class="section"><a href="multi__quickstart.html#_oauth2_protected_resource">1.2. OAuth2 Protected Resource</a></span></dt></dl></dd><dt><span class="chapter"><a href="multi__more_detail.html">2. More Detail</a></span></dt><dd><dl><dt><span class="section"><a href="multi__more_detail.html#_single_sign_on">2.1. Single Sign On</a></span></dt><dt><span class="section"><a href="multi__more_detail.html#_token_relay">2.2. Token Relay</a></span></dt><dd><dl><dt><span class="section"><a href="multi__more_detail.html#_client_token_relay">2.2.1. Client Token Relay</a></span></dt><dt><span class="section"><a href="multi__more_detail.html#_client_token_relay_in_zuul_proxy">2.2.2. Client Token Relay in Zuul Proxy</a></span></dt><dt><span class="section"><a href="multi__more_detail.html#_resource_server_token_relay">2.2.3. Resource Server Token Relay</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">3. Configuring Authentication Downstream of a Zuul Proxy</a></span></dt></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi_pr01.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">&nbsp;</td><td width="20%" align="center">&nbsp;</td><td width="40%" align="right" valign="top">&nbsp;</td></tr></table></div></body></html>

View File

@@ -0,0 +1,35 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -0,0 +1,9 @@
@IMPORT url("manual.css");
body.firstpage {
background: url("../images/background.png") no-repeat center top;
}
div.part h1 {
border-top: none;
}

View File

@@ -0,0 +1,6 @@
@IMPORT url("manual.css");
body {
background: url("../images/background.png") no-repeat center top;
}

View File

@@ -0,0 +1,344 @@
@IMPORT url("highlight.css");
html {
padding: 0pt;
margin: 0pt;
}
body {
color: #333333;
margin: 15px 30px;
font-family: Helvetica, Arial, Freesans, Clean, Sans-serif;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
code {
font-size: 16px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
:not(a)>code {
color: #6D180B;
}
:not(pre)>code {
background-color: #F2F2F2;
border: 1px solid #CCCCCC;
border-radius: 4px;
padding: 1px 3px 0;
text-shadow: none;
white-space: nowrap;
}
body>*:first-child {
margin-top: 0 !important;
}
div {
margin: 0pt;
}
hr {
border: 1px solid #CCCCCC;
background: #CCCCCC;
}
h1,h2,h3,h4,h5,h6 {
color: #000000;
cursor: text;
font-weight: bold;
margin: 30px 0 10px;
padding: 0;
}
h1,h2,h3 {
margin: 40px 0 10px;
}
h1 {
margin: 70px 0 30px;
padding-top: 20px;
}
div.part h1 {
border-top: 1px dotted #CCCCCC;
}
h1,h1 code {
font-size: 32px;
}
h2,h2 code {
font-size: 24px;
}
h3,h3 code {
font-size: 20px;
}
h4,h1 code,h5,h5 code,h6,h6 code {
font-size: 18px;
}
div.book,div.chapter,div.appendix,div.part,div.preface {
min-width: 300px;
max-width: 1200px;
margin: 0 auto;
}
p.releaseinfo {
font-weight: bold;
margin-bottom: 40px;
margin-top: 40px;
}
div.authorgroup {
line-height: 1;
}
p.copyright {
line-height: 1;
margin-bottom: -5px;
}
.legalnotice p {
font-style: italic;
font-size: 14px;
line-height: 1;
}
div.titlepage+p,div.titlepage+p {
margin-top: 0;
}
pre {
line-height: 1.0;
color: black;
}
a {
color: #4183C4;
text-decoration: none;
}
p {
margin: 15px 0;
text-align: left;
}
ul,ol {
padding-left: 30px;
}
li p {
margin: 0;
}
div.table {
margin: 1em;
padding: 0.5em;
text-align: center;
}
div.table table,div.informaltable table {
display: table;
width: 100%;
}
div.table td {
padding-left: 7px;
padding-right: 7px;
}
.sidebar {
line-height: 1.4;
padding: 0 20px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
}
.sidebar p.title {
color: #6D180B;
}
pre.programlisting,pre.screen {
font-size: 15px;
padding: 6px 10px;
background-color: #F8F8F8;
border: 1px solid #CCCCCC;
border-radius: 3px 3px 3px 3px;
clear: both;
overflow: auto;
line-height: 1.4;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #DDDDDD !important;
border-radius: 4px !important;
border-collapse: separate !important;
line-height: 1.6;
}
table thead {
background: #F5F5F5;
}
table tr {
border: none;
border-bottom: none;
}
table th {
font-weight: bold;
}
table th,table td {
border: none !important;
padding: 6px 13px;
}
table tr:nth-child(2n) {
background-color: #F8F8F8;
}
td p {
margin: 0 0 15px 0;
}
div.table-contents td p {
margin: 0;
}
div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist *
{
border: none !important;
background: none !important;
margin: 0;
}
div.important p,div.note p,div.tip p,div.warning p {
color: #6F6F6F;
line-height: 1.6;
}
div.important code,div.note code,div.tip code,div.warning code {
background-color: #F2F2F2 !important;
border: 1px solid #CCCCCC !important;
border-radius: 4px !important;
padding: 1px 3px 0 !important;
text-shadow: none !important;
white-space: nowrap !important;
}
.note th,.tip th,.warning th {
display: none;
}
.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td
{
border-right: 1px solid #CCCCCC !important;
padding-top: 10px;
}
div.calloutlist p,div.calloutlist td {
padding: 0;
margin: 0;
}
div.calloutlist>table>tbody>tr>td:first-child {
padding-left: 10px;
width: 30px !important;
}
div.important,div.note,div.tip,div.warning {
margin-left: 0px !important;
margin-right: 20px !important;
margin-top: 20px;
margin-bottom: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
div.toc {
line-height: 1.2;
}
dl,dt {
margin-top: 1px;
margin-bottom: 0;
}
div.toc>dl>dt {
font-size: 32px;
font-weight: bold;
margin: 30px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dt {
font-size: 24px;
font-weight: bold;
margin: 20px 0 10px 0;
display: block;
}
div.toc>dl>dd>dl>dd>dl>dt {
font-weight: bold;
font-size: 20px;
margin: 10px 0 0 0;
}
tbody.footnotes * {
border: none !important;
}
div.footnote p {
margin: 0;
line-height: 1;
}
div.footnote p sup {
margin-right: 6px;
vertical-align: middle;
}
div.navheader {
border-bottom: 1px solid #CCCCCC;
}
div.navfooter {
border-top: 1px solid #CCCCCC;
}
.title {
margin-left: -1em;
padding-left: 1em;
}
.title>a {
position: absolute;
visibility: hidden;
display: block;
font-size: 0.85em;
margin-top: 0.05em;
margin-left: -1em;
vertical-align: text-top;
color: black;
}
.title>a:before {
content: "\00A7";
}
.title:hover>a,.title>a:hover,.title:hover>a:hover {
visibility: visible;
}
.title:focus>a,.title>a:focus,.title:focus>a:focus {
outline: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@@ -0,0 +1,175 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Cloud Security</title><link rel="stylesheet" type="text/css" href="css/manual-singlepage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div lang="en" class="book"><div class="titlepage"><div><div><h1 class="title"><a name="d0e3"></a>Spring Cloud Security</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="preface"><a href="#d0e9"></a></span></dt><dt><span class="chapter"><a href="#_quickstart">1. Quickstart</a></span></dt><dd><dl><dt><span class="section"><a href="#_oauth2_single_sign_on">1.1. OAuth2 Single Sign On</a></span></dt><dt><span class="section"><a href="#_oauth2_protected_resource">1.2. OAuth2 Protected Resource</a></span></dt></dl></dd><dt><span class="chapter"><a href="#_more_detail">2. More Detail</a></span></dt><dd><dl><dt><span class="section"><a href="#_single_sign_on">2.1. Single Sign On</a></span></dt><dt><span class="section"><a href="#_token_relay">2.2. Token Relay</a></span></dt><dd><dl><dt><span class="section"><a href="#_client_token_relay">2.2.1. Client Token Relay</a></span></dt><dt><span class="section"><a href="#_client_token_relay_in_zuul_proxy">2.2.2. Client Token Relay in Zuul Proxy</a></span></dt><dt><span class="section"><a href="#_resource_server_token_relay">2.2.3. Resource Server Token Relay</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#_configuring_authentication_downstream_of_a_zuul_proxy">3. Configuring Authentication Downstream of a Zuul Proxy</a></span></dt></dl></div><div class="preface"><div class="titlepage"><div><div><h1 class="title"><a name="d0e9" href="#d0e9"></a></h1></div></div></div><p>Spring Cloud Security offers a set of primitives for building secure
applications and services with minimum fuss. A declarative model which
can be heavily configured externally (or centrally) lends itself to
the implementation of large systems of co-operating, remote components,
usually with a central indentity management service. It is also extremely
easy to use in a service platform like Cloud Foundry. Building on
Spring Boot and Spring Security OAuth2 we can quickly create systems that
implement common patterns like single sign on, token relay and token
exchange.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/asciidoc" target="_top">github</a>.</p></td></tr></table></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_quickstart" href="#_quickstart"></a>1.&nbsp;Quickstart</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_oauth2_single_sign_on" href="#_oauth2_single_sign_on"></a>1.1&nbsp;OAuth2 Single Sign On</h2></div></div></div><p>Here&#8217;s a Spring Cloud "Hello World" app with HTTP Basic
authentication and a single user account:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Grab('spring-boot-starter-security')</span></em>
<em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
String home() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello World'</span>
}
}</pre><p>
</p><p>You can run it with <code class="literal">spring run app.groovy</code> and watch the logs for the password (username is "user"). So far this is just the default for a Spring Boot app.</p><p>Here&#8217;s a Spring Cloud app with OAuth2 SSO:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableOAuth2Sso</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
String home() {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello World'</span>
}
}</pre><p>
</p><p>Spot the difference? This app will actually behave exactly the same as
the previous one, because it doesn&#8217;t know it&#8217;s OAuth2 credentals
yet.</p><p>You can register an app in github quite easily, so try that if you
want a production app on your own domain. If you are happy to test on
localhost:8080, then set up these properties in your application
configuration:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">security</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> oauth2</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> client</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> clientId</span>: bd1c0a783ccdd1c9b9e4
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> clientSecret</span>: <span class="hl-number">1</span>a9030fbca47a5b2c28e92f19050bb77824b5ad1
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> accessTokenUri</span>: https://github.com/login/oauth/access_token
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> userAuthorizationUri</span>: https://github.com/login/oauth/authorize
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> clientAuthenticationScheme</span>: form
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> resource</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> userInfoUri</span>: https://api.github.com/user
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> preferTokenInfo</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span></pre><p>
</p><p>run the app above and it will redirect to github for authorization. If
you are already signed into github you won&#8217;t even notice that it has
authenticated. These credentials will only work if your app is
running on port 8080.</p><p>To limit the scope that the client asks for when it obtains an access token
you can set <code class="literal">security.oauth2.client.scope</code> (comma separated or an array in YAML). By
default the scope is empty and it is up to to Authorization Server to
decide what the defaults should be, usually depending on the settings in
the client registration that it holds.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The examples above are all Groovy scripts. If you want to write the
same code in Java (or Groovy) you need to add Spring Security OAuth2
to the classpath (e.g. see the
<a class="link" href="https://github.com/spring-cloud-samples/sso" target="_top">sample here</a>).</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_oauth2_protected_resource" href="#_oauth2_protected_resource"></a>1.2&nbsp;OAuth2 Protected Resource</h2></div></div></div><p>You want to protect an API resource with an OAuth2 token? Here&#8217;s a
simple example (paired with the client above):</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Grab('spring-cloud-starter-security')</span></em>
<em><span class="hl-annotation" style="color: gray">@RestController</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableResourceServer</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
<em><span class="hl-annotation" style="color: gray">@RequestMapping('/')</span></em>
def home() {
[message: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">'Hello World'</span>]
}
}</pre><p>
</p><p>and</p><p><b>application.yml.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">security</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> oauth2</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> resource</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> userInfoUri</span>: https://api.github.com/user
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> preferTokenInfo</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">false</span></pre><p>
</p></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_more_detail" href="#_more_detail"></a>2.&nbsp;More Detail</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_single_sign_on" href="#_single_sign_on"></a>2.1&nbsp;Single Sign On</h2></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>All of the OAuth2 SSO and resource server features moved to Spring Boot
in version 1.3. You can find documentation in the
<a class="link" href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/" target="_top">Spring Boot user guide</a>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_token_relay" href="#_token_relay"></a>2.2&nbsp;Token Relay</h2></div></div></div><p>A Token Relay is where an OAuth2 consumer acts as a Client and
forwards the incoming token to outgoing resource requests. The
consumer can be a pure Client (like an SSO application) or a Resource
Server.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay" href="#_client_token_relay"></a>2.2.1&nbsp;Client Token Relay</h3></div></div></div><p>If your app is a user facing OAuth2 client (i.e. has declared
<code class="literal">@EnableOAuth2Sso</code> or <code class="literal">@EnableOAuth2Client</code>) then it has an
<code class="literal">OAuth2ClientContext</code> in request scope from Spring Boot. You can
create your own <code class="literal">OAuth2RestTemplate</code> from this context and an
autowired <code class="literal">OAuth2ProtectedResourceDetails</code>, and then the context will
always forward the access token downstream, also refreshing the access
token automatically if it expires. (These are features of Spring
Security and Spring Boot.)</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Boot (1.4.1) does not create an
<code class="literal">OAuth2ProtectedResourceDetails</code> automatically if you are using
<code class="literal">client_credentials</code> tokens. In that case you need to create your own
<code class="literal">ClientCredentialsResourceDetails</code> and configure it with
<code class="literal">@ConfigurationProperties("security.oauth2.client")</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay_in_zuul_proxy" href="#_client_token_relay_in_zuul_proxy"></a>2.2.2&nbsp;Client Token Relay in Zuul Proxy</h3></div></div></div><p>If your app also has a
<a class="link" href="http://cloud.spring.io/spring-cloud.html#netflix-zuul-reverse-proxy" target="_top">Spring
Cloud Zuul</a> embedded reverse proxy (using <code class="literal">@EnableZuulProxy</code>) then you
can ask it to forward OAuth2 access tokens downstream to the services
it is proxying. Thus the SSO app above can be enhanced simply like
this:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableOAuth2Sso</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableZuulProxy</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
}</pre><p>
</p><p>and it will (in addition to logging the user in and grabbing a token)
pass the authentication token downstream to the <code class="literal">/proxy/*</code>
services. If those services are implemented with
<code class="literal">@EnableResourceServer</code> then they will get a valid token in the
correct header.</p><p>How does it work? The <code class="literal">@EnableOAuth2Sso</code> annotation pulls in
<code class="literal">spring-cloud-starter-security</code> (which you could do manually in a
traditional app), and that in turn triggers some autoconfiguration for
a <code class="literal">ZuulFilter</code>, which itself is activated because Zuul is on the
classpath (via <code class="literal">@EnableZuulProxy</code>). The
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/OAuth2TokenRelayFilter.java" target="_top">filter</a>
just extracts an access token from the currently authenticated user,
and puts it in a request header for the downstream requests.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resource_server_token_relay" href="#_resource_server_token_relay"></a>2.2.3&nbsp;Resource Server Token Relay</h3></div></div></div><p>If your app has <code class="literal">@EnableResourceServer</code> you might want to relay the
incoming token downstream to other services. If you use a
<code class="literal">RestTemplate</code> to contact the downstream services then this is just a
matter of how to create the template with the right context.</p><p>If your service uses <code class="literal">UserInfoTokenServices</code> to authenticate incoming
tokens (i.e. it is using the <code class="literal">security.oauth2.user-info-uri</code>
configuration), then you can simply create an <code class="literal">OAuth2RestTemplate</code>
using an autowired <code class="literal">OAuth2ClientContext</code> (it will be populated by the
authentication process before it hits the backend code). Equivalently
(with Spring Boot 1.4), you could inject a
<code class="literal">UserInfoRestTemplateFactory</code> and grab its <code class="literal">OAuth2RestTemplate</code> in
your configuration. For example:</p><p><b>MyConfiguration.java.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory.getUserInfoRestTemplate();
}</pre><p>
</p><p>This rest template will then have the same <code class="literal">OAuth2ClientContext</code>
(request-scoped) that is used by the authentication filter, so you can
use it to send requests with the same access token.</p><p>If your app is not using <code class="literal">UserInfoTokenServices</code> but is still a client
(i.e. it declares <code class="literal">@EnableOAuth2Client</code> or <code class="literal">@EnableOAuth2Sso</code>), then
with Spring Security Cloud any <code class="literal">OAuth2RestOperations</code> that the user
creates from an <code class="literal">@Autowired</code> <code class="literal">@OAuth2Context</code> will also forward
tokens. This feature is implemented by default as an MVC handler
interceptor, so it only works in Spring MVC. If you are not using MVC
you could use a custom filter or AOP interceptor wrapping an
<code class="literal">AccessTokenContextRelay</code> to provide the same feature.</p><p>Here&#8217;s a basic
example showing the use of an autowired rest template created
elsewhere ("foo.com" is a Resource Server accepting the same tokens as
the surrounding app):</p><p><b>MyController.java.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> OAuth2RestOperations restTemplate;
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/relay")</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String relay() {
ResponseEntity&lt;String&gt; response =
restTemplate.getForEntity(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://foo.com/bar"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Success! ("</span> + response.getBody() + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")"</span>;
}</pre><p>
</p><p>If you don&#8217;t want to forward tokens (and that is a valid
choice, since you might want to act as yourself, rather than the
client that sent you the token), then you only need to create your own
<code class="literal">OAuth2Context</code> instead of autowiring the default one.</p><p>Feign clients will also pick up an interceptor that uses the
<code class="literal">OAuth2ClientContext</code> if it is available, so they should also do a
token relay anywhere where a <code class="literal">RestTemplate</code> would.</p></div></div></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_configuring_authentication_downstream_of_a_zuul_proxy" href="#_configuring_authentication_downstream_of_a_zuul_proxy"></a>3.&nbsp;Configuring Authentication Downstream of a Zuul Proxy</h1></div></div></div><p>You can control the authorization behaviour downstream of an
<code class="literal">@EnableZuulProxy</code> through the <code class="literal">proxy.auth.*</code> settings. Example:</p><p><b>application.yml.&nbsp;</b>
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">proxy</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> auth</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> routes</span>:
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> customers</span>: oauth2
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> stores</span>: passthru
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute"> recommendations</span>: none</pre><p>
</p><p>In this example the "customers" service gets an OAuth2 token relay,
the "stores" service gets a passthrough (the authorization header is
just passed downstream), and the "recommendations" service has its
authorization header removed. The default behaviour is to do a token
relay if there is a token available, and passthru otherwise.</p><p>See
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/ProxyAuthenticationProperties" target="_top">
ProxyAuthenticationProperties</a> for full details.</p></div></div></body></html>

View File

@@ -0,0 +1,287 @@
<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<book xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>Spring Cloud Security</title>
<date>2018-01-16</date>
</info>
<preface>
<title></title>
<simpara>Spring Cloud Security offers a set of primitives for building secure
applications and services with minimum fuss. A declarative model which
can be heavily configured externally (or centrally) lends itself to
the implementation of large systems of co-operating, remote components,
usually with a central indentity management service. It is also extremely
easy to use in a service platform like Cloud Foundry. Building on
Spring Boot and Spring Security OAuth2 we can quickly create systems that
implement common patterns like single sign on, token relay and token
exchange.</simpara>
<note>
<simpara>Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at <link xl:href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/asciidoc">github</link>.</simpara>
</note>
</preface>
<chapter xml:id="_quickstart">
<title>Quickstart</title>
<section xml:id="_oauth2_single_sign_on">
<title>OAuth2 Single Sign On</title>
<simpara>Here&#8217;s a Spring Cloud "Hello World" app with HTTP Basic
authentication and a single user account:</simpara>
<formalpara>
<title>app.groovy</title>
<para>
<programlisting language="java" linenumbering="unnumbered">@Grab('spring-boot-starter-security')
@Controller
class Application {
@RequestMapping('/')
String home() {
'Hello World'
}
}</programlisting>
</para>
</formalpara>
<simpara>You can run it with <literal>spring run app.groovy</literal> and watch the logs for the password (username is "user"). So far this is just the default for a Spring Boot app.</simpara>
<simpara>Here&#8217;s a Spring Cloud app with OAuth2 SSO:</simpara>
<formalpara>
<title>app.groovy</title>
<para>
<programlisting language="java" linenumbering="unnumbered">@Controller
@EnableOAuth2Sso
class Application {
@RequestMapping('/')
String home() {
'Hello World'
}
}</programlisting>
</para>
</formalpara>
<simpara>Spot the difference? This app will actually behave exactly the same as
the previous one, because it doesn&#8217;t know it&#8217;s OAuth2 credentals
yet.</simpara>
<simpara>You can register an app in github quite easily, so try that if you
want a production app on your own domain. If you are happy to test on
localhost:8080, then set up these properties in your application
configuration:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<programlisting language="yaml" linenumbering="unnumbered">security:
oauth2:
client:
clientId: bd1c0a783ccdd1c9b9e4
clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
accessTokenUri: https://github.com/login/oauth/access_token
userAuthorizationUri: https://github.com/login/oauth/authorize
clientAuthenticationScheme: form
resource:
userInfoUri: https://api.github.com/user
preferTokenInfo: false</programlisting>
</para>
</formalpara>
<simpara>run the app above and it will redirect to github for authorization. If
you are already signed into github you won&#8217;t even notice that it has
authenticated. These credentials will only work if your app is
running on port 8080.</simpara>
<simpara>To limit the scope that the client asks for when it obtains an access token
you can set <literal>security.oauth2.client.scope</literal> (comma separated or an array in YAML). By
default the scope is empty and it is up to to Authorization Server to
decide what the defaults should be, usually depending on the settings in
the client registration that it holds.</simpara>
<note>
<simpara>The examples above are all Groovy scripts. If you want to write the
same code in Java (or Groovy) you need to add Spring Security OAuth2
to the classpath (e.g. see the
<link xl:href="https://github.com/spring-cloud-samples/sso">sample here</link>).</simpara>
</note>
</section>
<section xml:id="_oauth2_protected_resource">
<title>OAuth2 Protected Resource</title>
<simpara>You want to protect an API resource with an OAuth2 token? Here&#8217;s a
simple example (paired with the client above):</simpara>
<formalpara>
<title>app.groovy</title>
<para>
<programlisting language="java" linenumbering="unnumbered">@Grab('spring-cloud-starter-security')
@RestController
@EnableResourceServer
class Application {
@RequestMapping('/')
def home() {
[message: 'Hello World']
}
}</programlisting>
</para>
</formalpara>
<simpara>and</simpara>
<formalpara>
<title>application.yml</title>
<para>
<programlisting language="yaml" linenumbering="unnumbered">security:
oauth2:
resource:
userInfoUri: https://api.github.com/user
preferTokenInfo: false</programlisting>
</para>
</formalpara>
</section>
</chapter>
<chapter xml:id="_more_detail">
<title>More Detail</title>
<section xml:id="_single_sign_on">
<title>Single Sign On</title>
<note>
<simpara>All of the OAuth2 SSO and resource server features moved to Spring Boot
in version 1.3. You can find documentation in the
<link xl:href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/">Spring Boot user guide</link>.</simpara>
</note>
</section>
<section xml:id="_token_relay">
<title>Token Relay</title>
<simpara>A Token Relay is where an OAuth2 consumer acts as a Client and
forwards the incoming token to outgoing resource requests. The
consumer can be a pure Client (like an SSO application) or a Resource
Server.</simpara>
<section xml:id="_client_token_relay">
<title>Client Token Relay</title>
<simpara>If your app is a user facing OAuth2 client (i.e. has declared
<literal>@EnableOAuth2Sso</literal> or <literal>@EnableOAuth2Client</literal>) then it has an
<literal>OAuth2ClientContext</literal> in request scope from Spring Boot. You can
create your own <literal>OAuth2RestTemplate</literal> from this context and an
autowired <literal>OAuth2ProtectedResourceDetails</literal>, and then the context will
always forward the access token downstream, also refreshing the access
token automatically if it expires. (These are features of Spring
Security and Spring Boot.)</simpara>
<note>
<simpara>Spring Boot (1.4.1) does not create an
<literal>OAuth2ProtectedResourceDetails</literal> automatically if you are using
<literal>client_credentials</literal> tokens. In that case you need to create your own
<literal>ClientCredentialsResourceDetails</literal> and configure it with
<literal>@ConfigurationProperties("security.oauth2.client")</literal>.</simpara>
</note>
</section>
<section xml:id="_client_token_relay_in_zuul_proxy">
<title>Client Token Relay in Zuul Proxy</title>
<simpara>If your app also has a
<link xl:href="http://cloud.spring.io/spring-cloud.html#netflix-zuul-reverse-proxy">Spring
Cloud Zuul</link> embedded reverse proxy (using <literal>@EnableZuulProxy</literal>) then you
can ask it to forward OAuth2 access tokens downstream to the services
it is proxying. Thus the SSO app above can be enhanced simply like
this:</simpara>
<formalpara>
<title>app.groovy</title>
<para>
<programlisting language="java" linenumbering="unnumbered">@Controller
@EnableOAuth2Sso
@EnableZuulProxy
class Application {
}</programlisting>
</para>
</formalpara>
<simpara>and it will (in addition to logging the user in and grabbing a token)
pass the authentication token downstream to the <literal>/proxy/*</literal>
services. If those services are implemented with
<literal>@EnableResourceServer</literal> then they will get a valid token in the
correct header.</simpara>
<simpara>How does it work? The <literal>@EnableOAuth2Sso</literal> annotation pulls in
<literal>spring-cloud-starter-security</literal> (which you could do manually in a
traditional app), and that in turn triggers some autoconfiguration for
a <literal>ZuulFilter</literal>, which itself is activated because Zuul is on the
classpath (via <literal>@EnableZuulProxy</literal>). The
<link xl:href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/OAuth2TokenRelayFilter.java">filter</link>
just extracts an access token from the currently authenticated user,
and puts it in a request header for the downstream requests.</simpara>
</section>
<section xml:id="_resource_server_token_relay">
<title>Resource Server Token Relay</title>
<simpara>If your app has <literal>@EnableResourceServer</literal> you might want to relay the
incoming token downstream to other services. If you use a
<literal>RestTemplate</literal> to contact the downstream services then this is just a
matter of how to create the template with the right context.</simpara>
<simpara>If your service uses <literal>UserInfoTokenServices</literal> to authenticate incoming
tokens (i.e. it is using the <literal>security.oauth2.user-info-uri</literal>
configuration), then you can simply create an <literal>OAuth2RestTemplate</literal>
using an autowired <literal>OAuth2ClientContext</literal> (it will be populated by the
authentication process before it hits the backend code). Equivalently
(with Spring Boot 1.4), you could inject a
<literal>UserInfoRestTemplateFactory</literal> and grab its <literal>OAuth2RestTemplate</literal> in
your configuration. For example:</simpara>
<formalpara>
<title>MyConfiguration.java</title>
<para>
<programlisting language="java" linenumbering="unnumbered">@Bean
public OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
return factory.getUserInfoRestTemplate();
}</programlisting>
</para>
</formalpara>
<simpara>This rest template will then have the same <literal>OAuth2ClientContext</literal>
(request-scoped) that is used by the authentication filter, so you can
use it to send requests with the same access token.</simpara>
<simpara>If your app is not using <literal>UserInfoTokenServices</literal> but is still a client
(i.e. it declares <literal>@EnableOAuth2Client</literal> or <literal>@EnableOAuth2Sso</literal>), then
with Spring Security Cloud any <literal>OAuth2RestOperations</literal> that the user
creates from an <literal>@Autowired</literal> <literal>@OAuth2Context</literal> will also forward
tokens. This feature is implemented by default as an MVC handler
interceptor, so it only works in Spring MVC. If you are not using MVC
you could use a custom filter or AOP interceptor wrapping an
<literal>AccessTokenContextRelay</literal> to provide the same feature.</simpara>
<simpara>Here&#8217;s a basic
example showing the use of an autowired rest template created
elsewhere ("foo.com" is a Resource Server accepting the same tokens as
the surrounding app):</simpara>
<formalpara>
<title>MyController.java</title>
<para>
<programlisting language="java" linenumbering="unnumbered">@Autowired
private OAuth2RestOperations restTemplate;
@RequestMapping("/relay")
public String relay() {
ResponseEntity&lt;String&gt; response =
restTemplate.getForEntity("https://foo.com/bar", String.class);
return "Success! (" + response.getBody() + ")";
}</programlisting>
</para>
</formalpara>
<simpara>If you don&#8217;t want to forward tokens (and that is a valid
choice, since you might want to act as yourself, rather than the
client that sent you the token), then you only need to create your own
<literal>OAuth2Context</literal> instead of autowiring the default one.</simpara>
<simpara>Feign clients will also pick up an interceptor that uses the
<literal>OAuth2ClientContext</literal> if it is available, so they should also do a
token relay anywhere where a <literal>RestTemplate</literal> would.</simpara>
</section>
</section>
</chapter>
<chapter xml:id="_configuring_authentication_downstream_of_a_zuul_proxy">
<title>Configuring Authentication Downstream of a Zuul Proxy</title>
<simpara>You can control the authorization behaviour downstream of an
<literal>@EnableZuulProxy</literal> through the <literal>proxy.auth.*</literal> settings. Example:</simpara>
<formalpara>
<title>application.yml</title>
<para>
<programlisting language="yaml" linenumbering="unnumbered">proxy:
auth:
routes:
customers: oauth2
stores: passthru
recommendations: none</programlisting>
</para>
</formalpara>
<simpara>In this example the "customers" service gets an OAuth2 token relay,
the "stores" service gets a passthrough (the authorization header is
just passed downstream), and the "recommendations" service has its
authorization header removed. The default behaviour is to do a token
relay if there is a token available, and passthru otherwise.</simpara>
<simpara>See
<link xl:href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/ProxyAuthenticationProperties">
ProxyAuthenticationProperties</link> for full details.</simpara>
</chapter>
</book>