Saml 2.0 メタデータ

Spring Security は、アサーティングパーティのメタデータを解析して AssertingPartyMetadata インスタンスを生成したり、RelyingPartyRegistration インスタンスから証明書利用者のメタデータを公開したりできます。

<saml2:IDPSSODescriptor> メタデータの解析

RelyingPartyRegistrations を使用して、アサーティングパーティのメタデータを解析できます。

OpenSAML ベンダーサポートを使用する場合、結果の AssertingPartyMetadata は型 OpenSamlAssertingPartyDetails になります。これは、以下を実行することで、基礎となる OpenSAML XMLObject を取得できることを意味します。

  • Java

  • Kotlin

OpenSamlAssertingPartyDetails details = (OpenSamlAssertingPartyDetails)
        registration.getAssertingPartyMetadata();
EntityDescriptor openSamlEntityDescriptor = details.getEntityDescriptor();
val details: OpenSamlAssertingPartyDetails =
        registration.getAssertingPartyMetadata() as OpenSamlAssertingPartyDetails
val openSamlEntityDescriptor: EntityDescriptor = details.getEntityDescriptor()

AssertingPartyMetadataRepository を使用する

また、アサーションパーティのメタデータの取得のみを許可するインターフェースである AssertingPartyMetadataRepository を使用すると、RelyingPartyRegistrations よりも対象を絞ることもできます。

これにより、次の 3 つの貴重な機能が可能になります。

  • 実装では、有効期限を考慮した方法でアサーションパーティのメタデータをリフレッシュできます。

  • RelyingPartyRegistrationRepository の実装により、依存当事者とそれに対応する 1 つまたは複数の主張当事者との関連をより簡単に表現できます。

  • 実装はメタデータ署名を検証できる

例: OpenSaml4AssertingPartyMetadataRepository は OpenSAML の MetadataResolver と API を使用し、その実装では有効期限を考慮して基礎となるメタデータを定期的にリフレッシュします。

つまり、わずか数行のコードでリフレッシュ可能な RelyingPartyRegistrationRepository を作成できるようになりました。

  • Java

  • Kotlin

@Component
public class RefreshableRelyingPartyRegistrationRepository
        implements IterableRelyingPartyRegistrationRepository {

	private final AssertingPartyMetadataRepository metadata =
            OpenSamlAssertingPartyMetadataRepository
                .fromTrustedMetadataLocation("https://idp.example.org/metadata").build();

	@Override
    public RelyingPartyRegistration findByRegistrationId(String registrationId) {
		AssertingPartyMetadata metadata = this.metadata.findByEntityId(registrationId);
        if (metadata == null) {
            return null;
        }
		return applyRelyingParty(metadata);
    }

	@Override
    public Iterator<RelyingPartyRegistration> iterator() {
		return StreamSupport.stream(this.metadata.spliterator(), false)
            .map(this::applyRelyingParty).iterator();
    }

	private RelyingPartyRegistration applyRelyingParty(AssertingPartyMetadata metadata) {
		return RelyingPartyRegistration.withAssertingPartyMetadata(metadata)
            // apply any relying party configuration
            .build();
	}

}
@Component
class RefreshableRelyingPartyRegistrationRepository : IterableRelyingPartyRegistrationRepository {

    private val metadata: AssertingPartyMetadataRepository =
        OpenSamlAssertingPartyMetadataRepository.fromTrustedMetadataLocation(
            "https://idp.example.org/metadata").build()

    fun findByRegistrationId(registrationId:String?): RelyingPartyRegistration {
        val metadata = this.metadata.findByEntityId(registrationId)
        if (metadata == null) {
            return null
        }
        return applyRelyingParty(metadata)
    }

    fun iterator(): Iterator<RelyingPartyRegistration> {
        return StreamSupport.stream(this.metadata.spliterator(), false)
            .map(this::applyRelyingParty).iterator()
    }

    private fun applyRelyingParty(metadata: AssertingPartyMetadata): RelyingPartyRegistration {
        val details: AssertingPartyMetadata = metadata as AssertingPartyMetadata
        return RelyingPartyRegistration.withAssertingPartyMetadata(details)
            // apply any relying party configuration
            .build()
    }
 }
OpenSaml4AssertingPartyMetadataRepository にはコンストラクターも付属しているため、カスタム MetadataResolver を提供できます。基盤となる MetadataResolver が有効期限切れとリフレッシュを実行するため、コンストラクターを直接使用する場合は、それを実行する実装を提供することによってのみこれらの機能を取得できます。

メタデータ署名の検証

次のように適切な Saml2X509Credential セットを提供することで、OpenSaml4AssertingPartyMetadataRepository を使用してメタデータ署名を検証することもできます。

  • Java

  • Kotlin

OpenSamlAssertingPartyMetadataRepository.withMetadataLocation("https://idp.example.org/metadata")
    .verificationCredentials((c) -> c.add(myVerificationCredential))
    .build();
OpenSamlAssertingPartyMetadataRepository.withMetadataLocation("https://idp.example.org/metadata")
    .verificationCredentials({ c : Collection<Saml2X509Credential> ->
        c.add(myVerificationCredential) })
    .build()
資格情報が提供されない場合、コンポーネントは署名の検証を実行しません。

<saml2:SPSSODescriptor> メタデータの作成

以下に示すように、saml2Metadata DSL メソッドを使用してメタデータエンドポイントを公開できます。

  • Java

  • Kotlin

http
    // ...
    .saml2Login(withDefaults())
    .saml2Metadata(withDefaults());
http {
    //...
    saml2Login { }
    saml2Metadata { }
}

このメタデータエンドポイントを使用して、依存パーティをアサーティングパーティに登録できます。これは、メタデータエンドポイントを提供するための正しいフォームフィールドを見つけるのと同じくらい簡単です。

デフォルトでは、メタデータエンドポイントは /saml2/metadata ですが、/saml2/metadata/{registrationId} および /saml2/service-provider-metadata/{registrationId} にも応答します。

これは、DSL で metadataUrl メソッドを呼び出すことで変更できます。

  • Java

  • Kotlin

.saml2Metadata((saml2) -> saml2.metadataUrl("/saml/metadata"))
saml2Metadata {
	metadataUrl = "/saml/metadata"
}

RelyingPartyRegistration のルックアップ方法の変更

使用する RelyingPartyRegistration を特定する別の方法がある場合は、以下のように独自の Saml2MetadataResponseResolver を構成できます。

  • Java

  • Kotlin

@Bean
Saml2MetadataResponseResolver metadataResponseResolver(RelyingPartyRegistrationRepository registrations) {
	RequestMatcherMetadataResponseResolver metadata = new RequestMatcherMetadataResponseResolver(
			(id) -> registrations.findByRegistrationId("relying-party"));
	metadata.setMetadataFilename("metadata.xml");
	return metadata;
}
@Bean
fun metadataResponseResolver(val registrations: RelyingPartyRegistrationRepository): Saml2MetadataResponseResolver {
    val metadata = new RequestMatcherMetadataResponseResolver(
			id: String -> registrations.findByRegistrationId("relying-party"))
	metadata.setMetadataFilename("metadata.xml")
	return metadata
}