Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

unmigrated-inline-wiki-markup
{span:style=font-size:2em;font-weight:bold} JAX-RS: SAML {span}

...

Table of Contents

Introduction

CXF 2.5.0

...

introduces

...

an

...

initial

...

support

...

for

...

working

...

with

...

SAML2

...

assertions.

...

So

...

far

...

the

...

main

...

focus

...

has

...

been

...

put

...

on

...

making

...

sure

...

SAML

...

assertions

...

can

...

be

...

included

...

in

...

HTTP

...

requests

...

targeted

...

at

...

application

...

endpoints:

...

embedded

...

inside

...

XML

...

payloads

...

or

...

passed

...

as

...

encoded

...

HTTP

...

header

...

or

...

form

...

values.

...

See

...

also

...

JAX-RS

...

XML

...

Security

...

.

...

Maven

...

dependencies

Code Block
xml
xml


{code:xml}
<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-rs-security-xml</artifactId>
  <version>2.5.0</version>
</dependency>
{code}

This

...

module

...

depends

...

on

...

CXF

...

WS-Security

...

and

...

Apache

...

WSS4J

...

modules,

...

due

...

to

...

them

...

containing

...

a

...

lot

...

of

...

useful

...

utility

...

code.

...


We

...

will

...

see

...

in

...

time

...

if

...

it

...

will

...

make

...

sense

...

to

...

exclude

...

such

...

dependencies

...

or

...

not.

Enveloped SAML assertions

Payload:

Code Block
xml
xml
 

h1. Enveloped SAML assertions

Payload:

{code:xml}
<env:Envelope xmlns:env="http://org.apache.cxf/rs/env">

<Book ID="67ca6441-0c4e-4430-af0e-9463ce9226aa">
  <id>125</id>
  <name>CXF</name>
</Book>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <!-- Book signature, omitted for brewity -->
</ds:Signature>

<!-- SAML assertion with an enveloped signature --> 
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_62D574706635C0B9F413203247720501" IssueInstant="2011-11-03T12:52:52.050Z" Version="2.0" xsi:type="saml2:AssertionType">

<saml2:Issuer>https://idp.example.org/SAML2</saml2:Issuer>

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:SignedInfo>
    <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
    <ds:Reference URI="#_62D574706635C0B9F413203247720501">
      <ds:Transforms>
       <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
       <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
         <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
       </ds:Transform>
      </ds:Transforms>
      <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
      <ds:DigestValue>IDD9nFocVm/7FpUbiGI3ZvpY2ps=</ds:DigestValue>
    </ds:Reference>
   </ds:SignedInfo>
   <ds:SignatureValue>JA2I7u/SmNsXGgWNdrLSovkipiM3JmGHsmpoP0EeIOwPwnLMx0WvV0C3xNGNiT1jOBe2uv8+WchtPoppGTC2JTJVX/t8PmKQCYZo4kVJo6Nmsjbn5kp7ejWuOYynvrUheQeTLU8e5CQmuS6L4VYaMVV2ETtb0VvpKjoQKHOC+co=</ds:SignatureValue>
   <ds:KeyInfo>
    <ds:X509Data>
     <ds:X509Certificate><!-- Omitted for brewity --> </ds:X509Certificate>
    </ds:X509Data>
   </ds:KeyInfo>
 </ds:Signature>

 <saml2:Subject>
   <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="www.mock-sts.com">uid=sts-client,o=mock-sts.com</saml2:NameID>
   <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"/>
 </saml2:Subject>

 <saml2:Conditions NotBefore="2011-11-03T12:52:52.063Z" NotOnOrAfter="2011-11-03T12:52:52.063Z">
  <saml2:AudienceRestriction>
   <saml2:Audience>https://sp.example.com/SAML2</saml2:Audience>
  </saml2:AudienceRestriction>
 </saml2:Conditions>
 <saml2:AuthnStatement AuthnInstant="2011-11-03T12:52:51.981Z" SessionIndex="123456">
    <saml2:AuthnContext><saml2:AuthnContextClassRef/></saml2:AuthnContext>
 </saml2:AuthnStatement>

 <saml2:AttributeStatement>
    <saml2:Attribute FriendlyName="subject-role" 
                     Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role" 
                     NameFormat="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
       <saml2:AttributeValue xsi:type="xs:string">user</saml2:AttributeValue>
    </saml2:Attribute>
    <saml2:Attribute Name="http://claims/authentication" 
                     NameFormat="http://claims/authentication-format">
       <saml2:AttributeValue xsi:type="xs:string">password</saml2:AttributeValue>
    </saml2:Attribute>
 </saml2:AttributeStatement>
</saml2:Assertion>
</env:Envelope>
{code}

Note

...

that

...

Book

...

and

...

SAML

...

assertion

...

are

...

individually

...

signed

...

but

...

the

...

envelope

...

wrapper

...

itself

...

is

...

not.

...

Here

...

is

...

another

...

payload

...

showing

...

the

...

whole

...

enveloped

...

signed

...

including

...

Book

...

and

...

SAML

...

Assertion,

...

this

...

time

...

only

...

a

...

single

...

signature

...

will

...

be

...

available:

Code Block
xml
xml


{code:xml}
<env:Envelope xmlns:env="http://org.apache.cxf/rs/env" ID="e795cdd1-c19d-4a5c-8d86-e8a781af4787">

<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_C76E3D5BBEE4C4D87913203281641141" IssueInstant="2011-11-03T13:49:24.114Z" Version="2.0" xsi:type="saml2:AssertionType">
<saml2:Issuer>https://idp.example.org/SAML2</saml2:Issuer>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="www.mock-sts.com">uid=sts-client,o=mock-sts.com</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"/>
</saml2:Subject>
<saml2:Conditions NotBefore="2011-11-03T13:49:24.127Z" NotOnOrAfter="2011-11-03T13:49:24.127Z">
<saml2:AudienceRestriction>
<saml2:Audience>https://sp.example.com/SAML2</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2011-11-03T13:49:24.044Z" SessionIndex="123456">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef/>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute FriendlyName="subject-role" Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role" NameFormat="http://schemas.xmlsoap.org/ws/2005/05/identity/claims">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">user</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="http://claims/authentication" NameFormat="http://claims/authentication-format">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">password</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>

<Book>
<id>125</id>
<name>CXF</name>
</Book>

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#e795cdd1-c19d-4a5c-8d86-e8a781af4787"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>GR1pHd2JpxYiCzl6ouCmTZjq/AA=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>C2qUDOFwart2GHFjX6kB3E3z73AMXtRR/6Qjgyp6XP/vTn/Fr2epDNub3q+gNdT0KgjLE2rSynM3QTcpHov9C8l9a8VQquItaalr0XA7BJcxdFMxB7KEATKR9XtrmIEkiw9efM8M83iVux/ufCOWrt0Te2RLz+nRwzyEY49VQOQ=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate><!-- Omitted for brewity --></ds:X509Certificate></ds:X509Data><ds:KeyValue><ds:RSAKeyValue><ds:Modulus>vu747/VShQ85f16DGSc4Ixh9PVpGguyEqrCsK8q9XHOYX9l9/g5wEC6ZcR2FwfNsoaHcKNPjd5sSTzVtBWmQjfBEfIqwTR7vuihOxyNTwEzVwIJzvo7p8/aYxk+VdBtQxq4UweIcf/iFkUbM1cZ1oiXRQzciRBi+C1BQCQE0qzs=</ds:Modulus><ds:Exponent>AQAB</ds:Exponent></ds:RSAKeyValue></ds:KeyValue></ds:KeyInfo></ds:Signature></env:Envelope>
{code}

Server

...

configuration

...

fragment:

Code Block
xml
xml

{code:xml}
    <bean id="serviceBean" class="org.apache.cxf.systest.jaxrs.security.BookStore"/>
    <bean id="samlHandler" class="org.apache.cxf.rs.security.saml.SamlEnvelopedInHandler"/>
    
    <!-- only needed if the detached signature signing the application data is expected --> 
    <bean id="xmlSigHandler" class="org.apache.cxf.rs.security.xml.XmlSigInHandler"/>
    
    
    <jaxrs:server 
       address="https://localhost:${testutil.ports.jaxrs-saml}/samlxml"> 
       <jaxrs:serviceBeans>
          <ref bean="serviceBean"/>
       </jaxrs:serviceBeans>
       <jaxrs:providers>
          <ref bean="xmlSigHandler"/>
          <ref bean="samlHandler"/>
       </jaxrs:providers>
       
       <jaxrs:properties>
           <entry key="ws-security.signature.properties" 
                  value="org/apache/cxf/systest/jaxrs/security/alice.properties"/>
       </jaxrs:properties>
        
    </jaxrs:server>
{code}

Client

...

code:

Code Block
java
java

{code:java}
private WebClient createWebClient(String address, 
                                  boolean selfSigned) {
  JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
  bean.setAddress(address);
  
  Map<String, Object> properties = new HashMap<String, Object>();
  properties.put("ws-security.callback-handler", 
                "org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback");
  properties.put("ws-security.saml-callback-handler", 
                 "org.apache.cxf.systest.jaxrs.security.saml.SamlCallbackHandler");
  properties.put("ws-security.signature.username", "alice");
  properties.put("ws-security.signature.properties", 
                 "org/apache/cxf/systest/jaxrs/security/alice.properties");
  if (selfSigned) {
     properties.put("ws-security.self-sign-saml-assertion", "true");
  }
  bean.setProperties(properties);
        
  bean.getOutInterceptors().add(new SamlEnvelopedOutInterceptor(!selfSigned));
  XmlSigOutInterceptor xmlSig = new XmlSigOutInterceptor();
  if (selfSigned) {
      xmlSig.setStyle(XmlSigOutInterceptor.DETACHED_SIG);
  }
  return bean.createWebClient();
}
{code}

In

...

the

...

above

...

code,

...

the

...

"ws-security.self-sign-saml-assertion"

...

property,

...

if

...

set

...

to

...

true,

...

will

...

require

...

SamlEnvelopedOutInterceptor

...

to

...

get

...

a

...

SAML

...

assertion

...

self-signed,

...

by

...

adding

...

an

...

enveloped

...

signature

...

to

...

it.

...

When

...

we

...

also

...

need

...

to

...

sign

...

the

...

application

...

payload

...

such

...

as

...

Book

...

we

...

need

...

to

...

make

...

sure

...

that

...

a

...

detached

...

XML

...

signature

...

for

...

Book

...

is

...

created.

...

When

...

the

...

whole

...

envelope

...

is

...

signed

...

then

...

SamlEnvelopedOutInterceptor

...

needs

...

to

...

be

...

placed

...

before

...

XmlSigOutInterceptor

...

hence

...

the

...

"new

...

SamlEnvelopedOutInterceptor(!selfSigned)"

...

constructor

...

is

...

invoked.

...

SAML

...

assertions

...

in

...

Authorization

...

header

...

Logging

...

output:

Code Block
java
java


{code:java}
Address: https://localhost:9000/samlheader/bookstore/books/123
Http-Method: GET
Headers: {Accept=[application/xml], Authorization=[SAML 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], ...}
{code}

Note

...

that

...

the

...

Authorization

...

header

...

has

...

an

...

encoded

...

SAML

...

Assertion

...

as

...

its

...

value.

...

The

...

original

...

SAML

...

assertion

...

has

...

been

...

optionally

...

compressed

...

using

...

a

...

deflated

...

encoding

...

and

...

then

...

base64-encoded.

...

This

...

encoded

...

value

...

can

...

be

...

signed

...

itself

...

-

...

but

...

it

...

is

...

not

...

currently

...

possible.

...

Server

...

configuration

...

is

...

similar

...

to

...

the

...

one

...

from

...

the

...

Enveloped

...

SAML

...

Assertions

...

section,

...

the

...

only

...

difference

...

is

...

that

...

a

...

SAML

...

handler

...

needs

...

to

...

be

...

replaced:

Code Block
xml
xml


{code:xml}
    <bean id="serviceBean" class="org.apache.cxf.systest.jaxrs.security.BookStore"/>
    <bean id="samlHandler" class="org.apache.cxf.rs.security.saml.SamlHeaderInHandler"/>
    
    <!-- same as in the Enveloped SAML Assertions section --> 
{code}

Client

...

code:

Code Block
java
java

{code:java}
private WebClient createWebClient(String address, 
                                  boolean selfSigned) {
  JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
  bean.setAddress(address);
  
  Map<String, Object> properties = new HashMap<String, Object>();
  properties.put("ws-security.callback-handler", 
                "org.apache.cxf.systest.jaxrs.security.saml.KeystorePasswordCallback");
  properties.put("ws-security.saml-callback-handler", 
                 "org.apache.cxf.systest.jaxrs.security.saml.SamlCallbackHandler");
  properties.put("ws-security.signature.username", "alice");
  properties.put("ws-security.signature.properties", 
                 "org/apache/cxf/systest/jaxrs/security/alice.properties");
  if (selfSigned) {
     properties.put("ws-security.self-sign-saml-assertion", "true");
  }
  bean.setProperties(properties);
        
  bean.getOutInterceptors().add(new SamlHeaderOutInterceptor());
  
  return bean.createWebClient();
}
{code}


h1. SAML assertions as Form values

Logging output:

{code:java}

SAML assertions as Form values

Logging output:

Code Block
java
java
Address: https://localhost:9000/samlform/bookstore/books
Encoding: ISO-8859-1
Http-Method: POST
Content-Type: application/x-www-form-urlencoded
Headers: {Accept=[application/xml], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[2206], content-type=[application/x-www-form-urlencoded], Host=[localhost:9000], Pragma=[no-cache], User-Agent=[Apache CXF ${project.version}]}
Payload: name=CXF&id=125&SAMLToken=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
{code}

Note

...

that

...

only

...

form

...

'name'

...

and

...

'id'

...

fields

...

will

...

remain

...

after

...

the

...

SAML

...

handler

...

processes

...

a

...

SAML

...

assertion

...

encoded

...

in

...

the

...

SAMLToken

...

form

...

field.

...

The

...

original

...

SAML

...

assertion

...

has

...

been

...

optionally

...

compressed

...

using

...

a

...

deflated

...

encoding

...

and

...

then

...

base64-encoded.

...

This

...

encoded

...

value

...

can

...

be

...

signed

...

-

...

but

...

it

...

is

...

not

...

currently

...

possible.

...

Server

...

configuration

...

is

...

similar

...

to

...

the

...

one

...

from

...

the

...

Enveloped

...

SAML

...

Assertions

...

section,

...

the

...

only

...

difference

...

is

...

that

...

a

...

SAML

...

handler

...

needs

...

to

...

be

...

replaced:

Code Block
xml
xml


{code:xml}
    <bean id="serviceBean" class="org.apache.cxf.systest.jaxrs.security.BookStore"/>
    <bean id="samlHandler" class="org.apache.cxf.rs.security.saml.SamlFormInHandler"/>
    
    <!-- same as in the Enveloped SAML Assertions section --> 
{code}

The

...

client

...

code

...

is

...

the

...

same

...

as

...

in

...

the

...

SAML

...

assertions

...

in

...

Authorization

...

header

...

section

...

except

...

than

...

an

...

instance

...

of

...

SamlFormOutInterceptor

...

has

...

to

...

be

...

registered:

Code Block
java
java
 
{code:java}
bean.getOutInterceptors().add(new SamlFormOutInterceptor());
{code}

h1. Creating SAML Assertions

If you use CXF 

Creating SAML Assertions

If you use CXF JAX-RS

...

client

...

API

...

to

...

experiment

...

with

...

SAML

...

then

...

all

...

you

...

need

...

to

...

do

...

is

...

to

...

register

...

an

...

appropriate

...

out

...

interceptor

...

as

...

shown

...

in

...

the

...

above

...

code

...

fragments.

...

The

...

interceptor

...

will

...

ensure

...

that

...

a

...

SAML

...

assertion

...

is

...

created

...

and

...

added

...

inside

...

the

...

XML

...

envelope,

...

as

...

a

...

form

...

or

...

HTTP

...

header

...

value.

...


All

...

of

...

the

...

SAML

...

output

...

interceptors

...

depend

...

on

...

a

...

"ws-security.saml-callback-handler"

...

property

...

linking

...

to

...

a

...

custom

...

javax.security.auth.callback.Callback

...

implementation

...

which

...

in

...

its

...

handle(Callbacks)

...

method

...

provides

...

the

...

information

...

which

...

is

...

needed

...

to

...

create

...

a

...

SAML

...

assertion

...

to

...

a

...

org.apache.ws.security.saml.ext.SAMLCallback

...

Callback

...

instance,

...

for

...

example,

...

see

...

this

...

custom

...

implementation

...

.

More involved cases with SAML assertions being created by identity providers will be supported, with the help of CXF (WS) STSClient when needed.

SAML Assertion Validation

When SAML assertions are received on the server side, they are validated to make sure that the enveloped signatures are correct. SubjectConfirmation methods (sender-vouches, holder-of-key,

...

bearer)

...

are

...

also

...

checked.

...


The

...

validation

...

can

...

be

...

delegated

...

to

...

STS

...

if

...

needed.

...

By

...

default,

...

server

...

side

...

SAML

...

handlers

...

have

...

a

...

"samlValidator"

...

property

...

set

...

to

...

an

...

instance

...

of

...

org.apache.ws.security.validate.SamlAssertionValidator

...

which

...

does

...

a

...

thorough

...

validation

...

of

...

the

...

assertion.

...

If

...

needed

...

org.apache.cxf.ws.security.trust.STSSamlAssertionValidator

...

can

...

be

...

set

...

instead

...

which

...

will

...

use

...

STS

...

to

...

validate

...

the

...

assertion.

...


Custom

...

validators

...

extending

...

WSS4J

...

SamlAssertionValidator

...

and

...

doing

...

the

...

additional

...

application-specific

...

validation

...

can

...

be

...

registered

...

if

...

needed.

...

Note

...

the

...

fact

...

that

...

the

...

default

...

validation

...

relies

...

a

...

lot

...

on

...

the

...

code

...

heavily

...

utilized

...

by

...

the

...

WS-Security

...

implementation

...

should

...

be

...

of

...

no

...

concern

...

-

...

it

...

is

...

an

...

example

...

of

...

the

...

integration

...

on

...

its

...

own

...

in

...

order

...

to

...

get

...

the

...

validation

...

done.

...

For

...

example,

...

WS-*

...

STS

...

are

...

heavily

...

used

...

in

...

the

...

enterprise

...

today

...

and

...

it

...

simply

...

makes

...

a

...

complete

...

sense

...

to

...

rely

...

on

...

it

...

to

...

validate

...

a

...

SAML

...

assertion

...

if

...

it

...

is

...

possible.

...

SubjectConfirmation

...

sender-vouches

...

and

...

holder-of-key

...

methods

...

can

...

be

...

easily

...

validated

...

with

...

enveloped

...

SAML

...

assertions

...

given

...

that

...

the

...

embedded

...

SAML

...

signatures

...

and

...

key

...

info

...

can

...

be

...

checked

...

against

...

the

...

signature

...

used

...

to

...

sign

...

the

...

envelope

...

or

...

a

...

custom

...

payload

...

like

...

Book.

...

At

...

the

...

moment

...

these

...

methods

...

can

...

not

...

be

...

properly

...

validated

...

when

...

the

...

assertion

...

is

...

provided

...

in

...

a

...

header

...

or

...

in

...

the

...

form,

...

the

...

additional

...

signature

...

signing

...

the

...

encoded

...

SAML

...

token

...

will

...

be

...

needed

...

-

...

this

...

will

...

be

...

supported

...

in

...

due

...

time.

...

Use

...

"bearer"

...

in

...

those

...

cases.

...

SAML

...

Authorization

...

SAML

...

assertions

...

may

...

contain

...

so-called

...

claims

...

which

...

are

...

represented

...

by

...

a

...

sequence

...

of

...

SAML

...

AttributeStatements

...

containing

...

one

...

or

...

more

...

Attributes,

...

for

...

example:

Code Block
xml
xml


{code:xml}
<saml2:Assertion>
 <!-- ... -->
 <saml2:AttributeStatement>
    <saml2:Attribute NameFormat="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"
                 Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role" 
                 FriendlyName="subject-role">
       <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">user</saml2:AttributeValue>
    </saml2:Attribute>
    <saml2:Attribute NameFormat="http://claims/authentication"
                     Name="http://claims/authentication-format">
        <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">password</saml2:AttributeValue>
    </saml2:Attribute>
 </saml2:AttributeStatement>
 <!-- ... -->
</saml2:Assertion>
{code}

An

...

individual

...

claim

...

is

...

scoped

...

by

...

NameFormat

...

and

...

Name

...

attribute.

...

NameFormat

...

is

...

similar

...

to

...

a

...

namespace,

...

while

...

Name

...

identifies

...

what

...

the

...

value

...

of

...

this

...

claim

...

represents,

...

for

...

example,

...

in

...

the

...

above

...

fragment

...

two

...

claims

...

are

...

provided,

...

one

...

has

...

a

...

value

...

"user"

...

which

...

represents

...

a

...

role

...

of

...

the

...

assertion's

...

Subject,

...

another

...

one

...

has

...

a

...

value

...

of

...

"password"

...

which

...

identifies

...

the

...

way

...

Subject

...

authenticated

...

itself,

...

i.e,

...

Subject

...

provided

...

its

...

password

...

(presumably

...

to

...

IDP).

...

Now,

...

what

...

is

...

interesting

...

is

...

to

...

see

...

if

...

it

...

is

...

possible

...

to

...

use

...

these

...

claims

...

with

...

Role-Based

...

Access-Control

...

(for

...

example,

...

with

...

endpoints

...

relying

...

on

...

@RolesAllowed

...

annotations)

...

as

...

well

...

as

...

with

...

the

...

more

...

complex

...

authorization

...

logic

...

(for

...

example,

...

let

...

this

...

resource

...

be

...

invoked

...

only

...

if

...

Subject

...

used

...

a

...

password

...

to

...

get

...

authenticated

...

at

...

IDP).

...

Claims

...

Based

...

Access

...

Control

...

CXF

...

JAX-RS

...

offers

...

an

...

extension

...

letting

...

users

...

to

...

enforce

...

a

...

new

...

fine-grained

...

Claims

...

Based

...

Access

...

Control

...

(CBAC)

...

based

...

on Claim and Claims annotations as well as ClaimMode enum class.

Note a package for Claim, Claims and ClaimMode annotations has changed from "org.apache.cxf.rs.security.saml.authorization" to "org.apache.cxf.security.claims.authorization". Starting from CXF 2.7.1, the default name format for claims is "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" instead of "http://schemas.xmlsoap.org/ws/2005/05/identity/claims".

Here is a simple code fragment:

Code Block
java
java

import org.apache.cxf.rs.security.saml.authorization.Claim;
import  [Claim|http://svn.apache.org/repos/asf/cxf/trunk/api/src/main/java/org/apache/cxf/security/claims/authorization/Claim.java] and [Claims|http://svn.apache.org/repos/asf/cxf/trunk/api/src/main/java/org/apache/cxf/security/claims/authorization/Claims.java] annotations as well as [ClaimMode|http://svn.apache.org/repos/asf/cxf/trunk/api/src/main/java/org/apache/cxf/security/claims/authorization/ClaimMode.java] enum class.   

*Note* a package for Claim, Claims and ClaimMode annotations has changed from "org.apache.cxf.rs.security.saml.authorization.Claims;

@Path("/bookstore")
public class to "org.apache.cxf.security.claims.authorization". Starting from CXF 2.7.1, the default name format for claims is "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" instead of "http://schemas.xmlsoap.org/ws/2005/05/identity/claims".

Here is a simple code fragment:
{code:java}
import org.apache.cxf.rs.security.saml.authorization.Claim;
import org.apache.cxf.rs.security.saml.authorization.Claims;

@Path("/bookstore")
public class SecureClaimBookStore {
    
    @POST
    @Path("/books")
    @Produces("application/xml")
    @Consumes("application/xml")
    @Claims({ 
        @Claim({"admin" }),
        @Claim(name = "http://claims/authentication-format", 
               format = "http://claims/authentication", 
               value = {"fingertip", "SecureClaimBookStore {
    
    @POST
    @Path("/books")
    @Produces("application/xml")
    @Consumes("application/xml")
    @Claims({ 
        @Claim({"admin" }),
        @Claim(name = "http://claims/authentication-format", 
               format = "http://claims/authentication", 
               value = {"fingertip", "smartcard" })
    })
    public Book addBook(Book book) {
        return book;
    }
    
}
{code}

SecureClaimBookStore.addBook(Book)

...

can

...

only

...

be

...

invoked

...

if

...

Subject

...

meets

...

the

...

following

...

requirement:

...

it

...

needs

...

to

...

have

...

a

...

Claim

...

with

...

a

...

value

...

"admin"

...

and

...

another

...

Claim

...

confirming

...

that

...

it

...

got

...

authenticated

...

using

...

either

...

a

...

'fingertip'

...

or

...

'smartcard'

...

method.

...

Note

...

that

...

@Claim(

...

{"admin"})

...

has

...

no

...

name

...

and

...

format

...

classifiers

...

set

...

-

...

it

...

relies

...

on

...

default

...

name

...

and

...

format

...

values,

...

namely

...

"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"

...

and

...

"urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"

...

("http://schemas.xmlsoap.org/ws/2005/05/identity/claims"

...

before

...

CXF

...

2.7.1)

...

respectively.

...

These

...

default

...

values

...

may

...

change

...

in

...

the

...

future

...

depending

...

on

...

which

...

claims

...

are

...

found

...

to

...

be

...

used

...

most

...

often

...

-

...

but

...

as

...

you

...

can

...

see

...

you

...

can

...

always

...

provide

...

name

...

and

...

format

...

values

...

which

...

will

...

scope

...

a

...

given

...

claim

...

value.

...

Note that in the above example, a Claim with the name "http://claims/authentication-format"

...

has

...

two

...

values,

...

'fingertip'

...

and

...

'smartcard'.

...

By

...

default,

...

in

...

order

...

to

...

meet

...

this

...

Claim,

...

Subject

...

needs

...

to

...

have

...

a

...

Claim

...

which

...

has

...

either

...

a

...

'fingertip'

...

or

...

'smartcard'

...

value.

...

If

...

it

...

is

...

expected

...

that

...

Subject

...

needs

...

to

...

have

...

a

...

Claim

...

which

...

has

...

both

...

'fingertip'

...

and

...

'smartcard'

...

values,

...

then

...

the

...

following

...

change

...

needs

...

to

...

be

...

done:

Code Block
java
java


{code:java}
import org.apache.cxf.security.claims.authorization.Claim;
import org.apache.cxf.security.claims.authorization.Claims;

@Path("/bookstore")
public class SecureClaimBookStore {
    
    @POST
    @Path("/books")
    @Produces("application/xml")
    @Consumes("application/xml")
    @Claims({ 
        @Claim({"admin" }),
        @Claim(name = "http://claims/authentication-format", 
               format = "http://claims/authentication", 
               value = {"fingertip", "smartcard" },
               matchAll = true)
    })
    public Book addBook(Book book) {
        return book;
    }
    
}
{code}
  
Claims can be specified using individual @Claim annotation, they can

Claims can be specified using individual @Claim annotation, they can be set at the class level and overridden at the method level and finally a lax mode of check can be specified:

Code Block
java
java
 be set at the class level and overridden at the method level and finally a lax mode of check can be specified:

{code:java}
import org.apache.cxf.security.claims.authorization.Claim;
import org.apache.cxf.security.claims.authorization.Claims;

@Path("/bookstore")
@Claim({"user"})
public class SecureClaimBookStore {
    
    @POST
    @Path("/books")
    @Produces("application/xml")
    @Consumes("application/xml")
    @Claims({ 
        @Claim({"admin" }),
        @Claim(name = "http://claims/authentication-format", 
               format = "http://claims/authentication", 
               value = {"fingertip", "smartcard" },
               matchAll = true)
    })
    public Book addBook(Book book) {
        return book;
    }

    @GET
    @Claim(name = "http://claims/authentication-format", 
               format = "http://claims/authentication", 
               value = {"password" },
               mode = ClaimMode.LAX)
    public Book getBook() {
        //...
    }

    @GET
    public BookList getBookList() {
        //...
    }
    
    
}
{code}

In

...

the

...

above

...

example,

...

getBookList()

...

can

...

be

...

invoked

...

if

...

Subject

...

has

...

a

...

Claim

...

with

...

the

...

value

...

"user";

...

addBook()

...

has

...

it

...

overridden

...

-

...

"admin"

...

is

...

expected

...

and

...

the

...

authentication

...

format

...

Claim

...

too;

...

getBook()

...

can

...

be

...

invoked

...

if

...

Subject

...

has

...

a

...

Claim

...

with

...

the

...

value

...

"user"

...

and

...

it

...

also

...

must

...

have

...

the

...

authentication

...

format

...

Claim

...

with

...

the

...

value

...

"password"

...

-

...

or

...

no

...

such

...

Claim

...

at

...

all

...

.

org.apache.cxf.rs.security.saml.authorization.ClaimsAuthorizingInterceptor

...

enforces

...

the

...

CBAC

...

rules.

...

This

...

filter

...

can

...

be

...

overridden

...

and

...

configured

...

with

...

the

...

rules

...

directly

...

which

...

can

...

be

...

useful

...

if

...

no

...

Claim-related

...

annotations

...

are

...

expected

...

in

...

the

...

code.

...

Map

...

nameAliases

...

and

...

formatAliases

...

properties

...

are

...

supported

...

to

...

make

...

@Claim

...

annotations

...

look

...

a

...

bit

...

simpler,

...

for

...

example:

Code Block
java
java

{code:java}
@Claim(name = "auth-format", format = "authentication", value = {"password" })
{code}
 
where 

where "auth-format"

...

and

...

"authentication"

...

are

...

aliases

...

for

...

"http://claims/authentication-format"

...

and

...

"http://claims/authentication"

...

respectively.

...

Given

...

the

...

above

...

example,

...

the

...

question

...

is

...

how

...

to

...

extract

...

the

...

information

...

available

...

in

...

a

...

SAML

...

Assertion

...

for

...

the

...

current

...

request

...

to

...

succeed

...

in

...

passing

...

through

...

the

...

security

...

filter

...

enforcing

...

the

...

CBAC

...

rules.

...

The

...

first

...

and

...

most

...

important

...

thing

...

which

...

needs

...

to

...

be

...

done

...

is

...

to

...

verify

...

that

...

an

...

assertion

...

Subject

...

can

...

be

...

mapped

...

to

...

a

...

recognized

...

identity

...

instance.

...

There

...

is

...

a

...

number

...

of

...

ways

...

a

...

Subject

...

can

...

be

...

validated.

...

If

...

STS

...

is

...

asked

...

to

...

validate

...

the

...

assertion

...

then

...

a

...

successful

...

response

...

from

...

IDP

...

will

...

likely

...

be

...

good

...

enough

...

for

...

CXF

...

to

...

trust

...

the

...

identity

...

of

...

the

...

provider.

...


If

...

the

...

assertion

...

signature

...

is

...

verified

...

locally

...

using

...

the

...

public

...

key

...

of

...

IDP

...

then

...

it

...

could

...

a

...

good

...

enough

...

confirmation

...

too.

...

Alternatively,

...

a custom validator, extending either org.apache.ws.security.validate.SamlAssertionValidator or CXF SAML SecurityContextProvider implementation can be registered with the server side SAML handler.

The latter option is preferred because not only one can validate Subject - but also ensure that a resulting SecurityContext will return a user Principal with a proper name - given that the actual Subject name available in the assertion may need to be translated to a name recognized by the local security stores or application. A combination of the assertion's Subject and AttributeStatement elements may need to be checked to establish a real name.

In cases like this you may want to register a custom SecurityContextProvider even if you have STS validating the assertion. Yet another reason is to retrieve the information about roles for a given Subject or map the assertion claims to roles for working with the RBAC to succeed, see the next section for more information.

Have a look please at this server configuration example:

Code Block
xml
xml
 custom validator, extending either org.apache.ws.security.validate.SamlAssertionValidator or CXF SAML [SecurityContextProvider|http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProvider.java] [implementation|http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/saml/authorization/SecurityContextProviderImpl.java] can be registered with the server side SAML handler. 

The latter option is preferred because not only one can validate Subject - but also ensure that a resulting SecurityContext will return a user Principal with a proper name - given that the actual Subject name available in the assertion may need to be translated to a name recognized by the local security stores or application. A combination of the assertion's Subject and AttributeStatement elements may need to be checked to establish a real name.

In cases like this you may want to register a custom SecurityContextProvider even if you have STS validating the assertion. Yet another reason is to retrieve the information about roles for a given Subject or map the assertion claims to roles for working with the RBAC to succeed, see the next section for more information.

Have a look please at this server configuration example:
{code:xml}

<bean id="serviceBeanClaims" class="org.apache.cxf.systest.jaxrs.security.saml.SecureClaimBookStore"/>
<bean id="samlEnvHandler" class="org.apache.cxf.rs.security.saml.SamlEnvelopedInHandler">
 <property name="securityContextProvider">
    <bean class="org.apache.cxf.systest.jaxrs.security.saml.CustomSecurityContextProvider"/>
 </property>
</bean>
    
<bean id="claimsHandler" 
     class="org.apache.cxf.rs.security.saml.authorization.ClaimsAuthorizingFilter">
    <property name="securedObject" ref="serviceBeanClaims"/>   
</bean>

<jaxrs:server address="/saml-claims"> 
       <jaxrs:serviceBeans>
          <ref bean="serviceBeanClaims"/>
       </jaxrs:serviceBeans>
       <jaxrs:providers>
          <ref bean="samlEnvHandler"/>
          <ref bean="claimsHandler"/>
       </jaxrs:providers>
</jaxrs:server>
{code}

An

...

instance

...

of

...

org.apache.cxf.rs.security.saml.authorization.ClaimsAuthorizingFilter

...

is

...

used

...

to

...

enforce

...

CBAC.

...

It's

...

a

...

simple

...

JAX-RS

...

filter

...

wrapper

...

around

...

ClaimsAuthorizingInterceptor.

...

SamlEnvelopedInHandler

...

processes

...

and

...

validates

...

SAML

...

assertions

...

and

...

it

...

also

...

relies

...

on

...

a

...

simple

...

CustomSecurityContextProvider

...

to

...

help

...

it

...

to

...

figure

...

out

...

what

...

the

...

actual

...

Subject

...

name

...

is.

...

A

...

more

...

involved

...

implementation

...

can

...

do

...

some

...

additional

...

validation

...

as

...

well

...

as

...

override

...

few

...

more

...

super

...

class

...

methods,

...

more

...

on

...

it

...

next.

...

The

...

claims

...

themselves

...

have

...

already

...

been

...

parsed

...

and

...

will

...

be

...

made

...

available

...

to

...

a

...

resulting

...

SecurityContext

...

which

...

ClaimsAuthorizingFilter

...

will

...

rely

...

upon.

...

Role Based Access Control

If you have an existing RBAC system (based on javax.annotation.security.RolesAllowed

...

or

...

even

...

org.springframework.security.annotation.Secured

...

annotations)

...

in

...

place

...

and

...

have

...

SAML

...

assertions

...

with

...

claims

...

that

...

are

...

known

...

to

...

represent

...

roles,

...

then

...

making

...

those

...

claims

...

work

...

with

...

the

...

RBAC

...

system

...

can

...

be

...

achieved

...

easily.

...

For

...

example,

...

given

...

this

...

code:

Code Block
java
java
java}
import org.springframework.security.annotation.Secured;

@Path("/bookstore")
@Claim({"user"})
public class SecureBookStore {
    
    @POST
    @Secured("admin")
    public Book addBook(Book book) {
        return book;
    }
}
{code}

where

...

@Secured

...

can

...

be

...

replaced

...

with

...

@RoledAllowed

...

if

...

needed,

...

the

...

following

...

configuration

...

will

...

do

...

it:

Code Block
xml
xml


{code:xml}

<bean id="serviceBeanRoles" class="org.apache.cxf.systest.jaxrs.security.saml.SecureBookStore"/>
<bean id="samlEnvHandler" class="org.apache.cxf.rs.security.saml.SamlEnvelopedInHandler">
 <property name="securityContextProvider">
    <bean class="org.apache.cxf.systest.jaxrs.security.saml.CustomSecurityContextProvider"/>
 </property>
</bean>

<bean id="authorizationInterceptor" class="org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor">
    <property name="securedObject" ref="serviceBean"/>
    <property name="annotationClassName" 
              value="org.springframework.security.annotation.Secured"/>
</bean>
    
<bean id="rolesHandler" class="org.apache.cxf.jaxrs.security.SimpleAuthorizingFilter">
    <property name="interceptor" ref="authorizationInterceptor"/>
</bean>
    
<jaxrs:server address="/saml-roles"> 
  <jaxrs:serviceBeans>
     <ref bean="serviceBeanRoles"/>
  </jaxrs:serviceBeans>
  <jaxrs:providers>
      <ref bean="samlEnvHandler"/>
      <ref bean="rolesHandler"/>
  </jaxrs:providers>
  
  <!-- If default role qualifier and format are not supported: 
       
  <jaxrs:properties>
     <entry key="org.apache.cxf.saml.claims.role.nameformat" 
                value="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/>
     <entry key="org.apache.cxf.saml.claims.role.qualifier" 
                value="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"/>
  </jaxrs:properties>
  -->
</jaxrs:server>
{code}

That

...

is

...

all

...

what

...

is

...

needed.

...

Note

...

that

...

in

...

order

...

to

...

help

...

the

...

default

...

SAML

...

SecurityContextProvider

...

figure

...

out

...

which

...

claims

...

are

...

roles,

...

one

...

can

...

set

...

the

...

two

...

properties

...

as

...

shown

...

above

...

-

...

this

...

not

...

needed

...

if

...

it's

...

known

...

that

...

claims

...

identifying

...

roles

...

have

...

NameFormat

...

and

...

Name

...

values

...

with

...

the

...

default

...

values,

...

which

...

are

...

"http://schemas.xmlsoap.org/ws/2005/05/identity/claims"

...

and

...

"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role"

...

respectively

...

at

...

the

...

moment.

...

Note

...

that

...

you

...

can

...

have

...

RBAC

...

and

...

CBAC

...

combined

...

for

...

a

...

more

...

sophisticated

...

access

...

control

...

rules

...

be

...

enforced

...

while

...

still

...

keeping

...

the

...

existing

...

code

...

relying

...

on

...

@RolesAllowed

...

or

...

@Secured

...

intact.

...

Override

...

ClaimsAuthorizingFilter

...

and

...

configure

...

it

...

with

...

the

...

Claims

...

rules

...

directly

...

and

...

register

...

it

...

alongside

...

SimpleAuthorizingFilter

...

and

...

here

...

you

...

go.

...

Also

...

note

...

how

...

SecureAnnotationsInterceptor

...

can

...

handle

...

different

...

types

...

of

...

role

...

annotations,

...

with

...

@RoledAllowed

...

being

...

supported

...

by

...

default.

...

SAML Web SSO Profile

Please see this page for more information