U kunt dit bericht negeren indien u dit account niet heeft aangemaakt.
+emailTestSubject=[KEYCLOAK] - SMTP testbericht
+emailTestBody=Dit is een testbericht
+emailTestBodyHtml=
Dit is een testbericht
+identityProviderLinkSubject=Koppel {0}
+identityProviderLinkBody=Iemand wil uw "{1}" account koppelen met "{0}" account van gebruiker {2}. Als u dit was, klik dan op de onderstaande link om de accounts te koppelen\n\n{3}\n\nDeze link zal over {4} minuten vervallen.\n\nAls u de accounts niet wilt koppelen, negeer dan dit bericht. Als u accounts koppelt, dan kunt u bij {1} inloggen via {0}.
+identityProviderLinkBodyHtml=
Iemand wil uw "{1}" account koppelen met "{0}" account van gebruiker {2}. Als u dit was, klik dan op de onderstaande link om de accounts te koppelen
Als u de accounts niet wilt koppelen, negeer dan dit bericht. Als u accounts koppelt, dan kunt u bij {1} inloggen via {0}.
+passwordResetSubject=Wijzig wachtwoord
+passwordResetBody=Iemand verzocht de aanmeldgegevens van uw {2} account te wijzigen. Als u dit was, klik dan op de onderstaande koppeling om ze te wijzigen.\n\n{0}\n\nDe link en de code zullen binnen {1} minuten vervallen.\n\nAls u uw aanmeldgegevens niet wilt wijzigen, negeer dan dit bericht en er zal niets gewijzigd worden.
+passwordResetBodyHtml=
Iemand verzocht de aanmeldgegevens van uw {2} account te wijzigen. Als u dit was, klik dan op de onderstaande koppeling om ze te wijzigen.
De link en de code zullen binnen {1} minuten vervallen.
Als u uw aanmeldgegevens niet wilt wijzigen, negeer dan dit bericht en er zal niets gewijzigd worden.
+executeActionsSubject=Wijzig uw account
+executeActionsBody=Uw beheerder heeft u verzocht uw {2} account te wijzigen. Klik op de onderstaande koppeling om dit proces te starten. \n\n{0}\n\nDeze link zal over {1} minuten vervallen. \n\nAls u niet over dit verzoek op de hoogte was, negeer dan dit bericht om uw account ongewijzigd te laten.
+executeActionsBodyHtml=
Uw beheerder heeft u verzocht uw {2} account te wijzigen. Klik op de onderstaande koppeling om dit proces te starten.
Als u niet over dit verzoek op de hoogte was, negeer dan dit bericht om uw account ongewijzigd te laten.
+eventLoginErrorSubject=Inlogfout
+eventLoginErrorBody=Er is een foutieve inlogpoging gedetecteerd op uw account om {0} vanuit {1}. Als u dit niet was, neem dan contact op met de beheerder.
+eventLoginErrorBodyHtml=
Er is een foutieve inlogpoging gedetecteerd op uw account om {0} vanuit {1}. Als u dit niet was, neem dan contact op met de beheerder.
+eventRemoveTotpSubject=TOTP verwijderd
+eventRemoveTotpBody=TOTP is verwijderd van uw account om {0} vanuit {1}. Als u dit niet was, neem dan contact op met uw beheerder.
+eventRemoveTotpBodyHtml=
TOTP is verwijderd van uw account om {0} vanuit {1}. Als u dit niet was, neem dan contact op met uw beheerder.
+eventUpdatePasswordSubject=Wachtwoord gewijzigd
+eventUpdatePasswordBody=Uw wachtwoord is gewijzigd om {0} door {1}. Als u dit niet was, neem dan contact op met uw beheerder.
+eventUpdatePasswordBodyHtml=
Uw wachtwoord is gewijzigd om {0} door {1}. Als u dit niet was, neem dan contact op met uw beheerder.
+eventUpdateTotpSubject=TOTP gewijzigd
+eventUpdateTotpBody=TOTP is gewijzigd voor uw account om {0} door {1}. Als u dit niet was, neem dan contact op met uw beheerder.
+eventUpdateTotpBodyHtml=
TOTP is gewijzigd voor uw account om {0} door {1}. Als u dit niet was, neem dan contact op met uw beheerder.
diff --git a/themes/src/main/resources-community/theme/base/email/theme.properties b/themes/src/main/resources-community/theme/base/email/theme.properties
index 6b2b6e8fac..b970c5e8f4 100644
--- a/themes/src/main/resources-community/theme/base/email/theme.properties
+++ b/themes/src/main/resources-community/theme/base/email/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru,sv
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,nl,no,pt-BR,ru,sv
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties
new file mode 100644
index 0000000000..13af95a91e
--- /dev/null
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties
@@ -0,0 +1,224 @@
+doLogIn=Inloggen
+doRegister=Registeer
+doCancel=Annuleer
+doSubmit=Verzenden
+doYes=Ja
+doNo=Nee
+doContinue=Doorgaan
+doAccept=Accepteren
+doDecline=Afwijzen
+doForgotPassword=Wachtwoord vergeten?
+doClickHere=Klik hier
+doImpersonate=Identiteit overnemen
+kerberosNotConfigured=Kerberos is niet geconfigureerd
+kerberosNotConfiguredTitle=Kerberos is niet geconfigureerd
+bypassKerberosDetail=U bent niet ingelogd via Kerberos of uw browser kan niet met Kerberos inloggen. Klik op 'doorgaan' om via een andere manier in te loggen
+kerberosNotSetUp=Kerberos is onjuist geconfigureerd. U kunt niet inloggen.
+registerWithTitle=Registeer met {0}
+registerWithTitleHtml={0}
+loginTitle=Inloggen bij {0}
+loginTitleHtml={0}
+impersonateTitle={0} Identiteit overnemen
+impersonateTitleHtml={0} Identiteit overnemen
+realmChoice=Realm
+unknownUser=Onbekende gebruiker
+loginTotpTitle=Mobile Authenticator Setup
+loginProfileTitle=Update accountinformatie
+loginTimeout=U bent te lang bezig geweest met inloggen. Het inlogproces begint overnieuw.
+oauthGrantTitle=Verleen Toegang
+oauthGrantTitleHtml={0}
+errorTitle=Er is een fout opgetreden...
+errorTitleHtml=Er is een fout opgetreden...
+emailVerifyTitle=E-mailadres-verificatie
+emailForgotTitle=Wachtwoord vergeten?
+updatePasswordTitle=Wachtwoord updaten
+codeSuccessTitle=Succescode
+codeErrorTitle=Foutcode: {0}
+
+termsTitle=Voorwaarden
+termsTitleHtml=Voorwaarden
+termsText=
Gedefinieerde voorwaarden
+recaptchaFailed=Ongeldige Recaptcha
+recaptchaNotConfigured=Recaptcha is verplicht, maar niet geconfigureerd
+consentDenied=Toestemming geweigerd.
+
+noAccount=Nieuwe gebruiker?
+username=Gebruikersnaam
+usernameOrEmail=Gebruikersnaam of e-mailadres
+firstName=Voornaam
+givenName=Voornaam
+lastName=Achternaam
+familyName=Familienaam
+email=E-mailadres
+password=Wachtwoord
+passwordConfirm=Bevestig wachtwoord
+passwordNew=Nieuw wachtwoord
+passwordNewConfirm=Bevestiging nieuwe wachtwoord
+rememberMe=Ingelogd blijven
+authenticatorCode=Authenticatiecode
+address=Adres
+postal_code=Postcode
+country=Land
+emailVerified=E-mailadres geverifieerd
+gssDelegationCredential=GSS delegatie Credential
+loginTotpStep1=Installeer FreeOTP of Google Authenticator op uw mobiele telefoon. Beide applicaties zijn beschikbaar in de Google Play en Apple App Store.
+loginTotpStep2=Open de applicatie en scan de barcode of voer de sleutel in
+loginTotpStep3=Voer de eenmalige code die door de applicatie is aangeleverd in en klik op 'Verzenden' om de setup te voltooien
+loginTotpOneTime=Eenmalige code
+
+oauthGrantRequest=Wilt u deze toegangsrechten verlenen?
+inResource=in
+
+emailVerifyInstruction1=Een e-mail met instructies om uw e-mailadres te verifiëren is zojuist verzonden.
+emailVerifyInstruction2=Heeft u geen verificatiecode ontvangen in uw e-mail?
+emailVerifyInstruction3=om opnieuw een e-mail te versturen.
+
+emailLinkIdpTitle=Link {0}
+emailLinkIdp1=Er is een e-mail met instructies verzonden om {0} account {1} te koppelen met uw {2} account.
+emailLinkIdp2=Heeft u geen verificatiecode in uw e-mail ontvangen?
+emailLinkIdp3=om opnieuw een e-mail te versturen.
+
+backToLogin=« Terug naar Inloggen
+
+emailInstruction=Voer uw gebruikersnaam of e-mailadres in en wij sturen u een e-mailbericht met instructies voor het aanmaken van een nieuw wachtwoord.
+
+copyCodeInstruction=Kopieer deze code en plak deze in uw applicatie:
+
+personalInfo=Persoonlijke informatie:
+role_realm-admin=Realm beheren
+role_create-realm=Realm aanmaken
+role_create-client=Client aanmaken
+role_view-realm=Bekijk realm
+role_view-users=Bekijk gebruikers
+role_view-clients=Bekijk clients
+role_view-events=Bekijk gebeurtenissen
+role_view-identity-providers=Bekijk identity providers
+role_manage-realm=Beheer realm
+role_manage-users=Gebruikers beheren
+role_manage-identity-providers=Beheer identity providers
+role_manage-clients=Beheer clients
+role_manage-events=Beheer gebeurtenissen
+role_view-profile=Profiel bekijken
+role_read-token=Token lezen
+role_offline-access=Offline toegang
+client_account=Account
+client_security-admin-console=Security Admin Console
+client_admin-cli=Admin CLI
+client_broker=Broker
+invalidUserMessage=Ongeldige gebruikersnaam of wachtwoord.
+invalidEmailMessage=Ongeldig e-mailadres.
+accountDisabledMessage=Account is uitgeschakeld, neem contact op met beheer.
+accountTemporarilyDisabledMessage=Account is tijdelijk uitgeschakeld, neem contact op met beheer of probeer het later opnieuw.
+expiredCodeMessage=Logintijd verlopen. Gelieve opnieuw in te loggen.
+
+missingFirstNameMessage=Voer uw voornaam in.
+missingLastNameMessage=Voer uw achternaam in.
+missingEmailMessage=Voer uw e-mailadres in.
+missingUsernameMessage=Voer uw gebruikersnaam in.
+missingPasswordMessage=Voer uw wachtwoord in.
+missingTotpMessage=Voer uw authenticatiecode in.
+notMatchPasswordMessage=Wachtwoorden komen niet overeen.
+invalidPasswordExistingMessage=Ongeldig bestaand wachtwoord.
+invalidPasswordConfirmMessage=Wachtwoord komt niet overeen met wachtwoordbevestiging.
+invalidTotpMessage=Ongeldige authenticatiecode.
+
+usernameExistsMessage=Gebruikersnaam bestaat al.
+emailExistsMessage=E-mailadres bestaat al.
+
+federatedIdentityExistsMessage=Gebruiker met {0} {1} bestaat al. Log in met het beheerdersaccount om het account te koppelen.
+
+confirmLinkIdpTitle=Account bestaat al
+federatedIdentityConfirmLinkMessage=Gebruiker met {0} {1} bestaat al. Hoe wilt u doorgaan?
+federatedIdentityConfirmReauthenticateMessage=Authenticeer als {0} om uw account te koppelen {1}
+confirmLinkIdpReviewProfile=Nalopen profiel
+confirmLinkIdpContinue=Voeg toe aan bestaande account
+
+configureTotpMessage=U moet de Mobile Authenticator configuren om uw account te activeren.
+updateProfileMessage=U moet uw gebruikersprofiel bijwerken om uw account te activeren.
+updatePasswordMessage=U moet uw wachtwoord wijzigen om uw account te activeren.
+verifyEmailMessage=U moet uw e-mailadres verifiëren om uw account te activeren.
+linkIdpMessage=U moet uw e-mailadres verifiëren om uw account te koppelen aan {0}.
+
+emailSentMessage=U ontvangt binnenkort een e-mail met verdere instructies.
+emailSendErrorMessage=Het versturen van de e-mail is mislukt, probeer het later opnieuw.
+
+accountUpdatedMessage=Uw account is gewijzigd.
+accountPasswordUpdatedMessage=Uw wachtwoord is gewijzigd.
+
+noAccessMessage=Geen toegang
+
+invalidPasswordMinLengthMessage=Ongeldig wachtwoord, de minimumlengte is {0} karakters.
+invalidPasswordMinDigitsMessage=Ongeldig wachtwoord, deze moet minstens {0} cijfers bevatten.
+invalidPasswordMinLowerCaseCharsMessage=Ongeldig wachtwoord, deze moet minstens {0} kleine letters bevatten.
+invalidPasswordMinUpperCaseCharsMessage=Ongeldig wachtwoord, deze moet minstens {0} hoofdletters bevatten.
+invalidPasswordMinSpecialCharsMessage=Ongeldig wachtwoord, deze moet minstens {0} speciale tekens bevatten.
+invalidPasswordNotUsernameMessage=Ongeldig wachtwoord, deze mag niet overeen komen met de gebruikersnaam.
+invalidPasswordRegexPatternMessage=Ongeldig wachtwoord, deze komt niet overeen met opgegeven reguliere expressie(s).
+invalidPasswordHistoryMessage=Ongeldig wachtwoord, deze mag niet overeen komen met een van de laatste {0} wachtwoorden.
+
+failedToProcessResponseMessage=Het verwerken van de respons is mislukt
+httpsRequiredMessage=HTTPS vereist
+realmNotEnabledMessage=Realm niet geactiveerd
+invalidRequestMessage=Ongeldige request
+failedLogout=Afmelden is mislukt
+unknownLoginRequesterMessage=De login requester is onbekend
+loginRequesterNotEnabledMessage=De login requester is niet geactiveerd
+bearerOnlyMessage=Bearer-only applicaties mogen geen browserlogin initiëren
+standardFlowDisabledMessage=Client mag geen browserlogin starten met het opgegeven response_type. Standard flow is uitgeschakeld voor de client.
+implicitFlowDisabledMessage=Client mag geen browserlogin starten met opgegeven response_type. Implicit flow is uitgeschakeld voor de klant.
+invalidRedirectUriMessage=Ongeldige redirect-URI
+unsupportedNameIdFormatMessage=Niet-ondersteunde NameIDFormat
+invalidRequesterMessage=Ongeldige requester
+registrationNotAllowedMessage=Registratie is niet toegestaan
+resetCredentialNotAllowedMessage=Het opnieuw instellen van de aanmeldgegevens is niet toegestaan
+permissionNotApprovedMessage=Recht verworpen.
+noRelayStateInResponseMessage=Geen relay state in antwoord van de identity provider.
+insufficientPermissionMessage=Onvoldoende rechten om identiteiten te koppelen.
+couldNotProceedWithAuthenticationRequestMessage=Het authenticatieverzoek naar de identity provider wordt afgebroken.
+couldNotObtainTokenMessage=Kon geen token bemachtigen van de identity provider.
+unexpectedErrorRetrievingTokenMessage=Onverwachte fout bij het ophalen van de token van de identity provider.
+unexpectedErrorHandlingResponseMessage=Onverwachte fout bij het verwerken van de respons van de identity provider.
+identityProviderAuthenticationFailedMessage=Verificatie mislukt. Er kon niet worden geauthenticeerd met de identity provider.
+identityProviderDifferentUserMessage=U bent geauthenticeerd als {0}, maar u werd verwacht als {1} geauthenticeerd te zijn
+couldNotSendAuthenticationRequestMessage=Kan het authenticatieverzoek niet verzenden naar de identity provider.
+unexpectedErrorHandlingRequestMessage=Onverwachte fout bij het verwerken van het authenticatieverzoek naar de identity provider.
+invalidAccessCodeMessage=Ongeldige toegangscode.
+sessionNotActiveMessage=Sessie inactief.
+invalidCodeMessage=Er is een fout opgetreden, probeer nogmaals in te loggen.
+identityProviderUnexpectedErrorMessage=Onverwachte fout tijdens de authenticatie met de identity provider
+identityProviderNotFoundMessage=Geen identity provider gevonden met deze naam.
+identityProviderLinkSuccess=Uw account is met succes gekoppeld aan {0} account {1}.
+staleCodeMessage=Deze pagina is verlopen. Keer terug naar uw applicatie om opnieuw in te loggen.
+realmSupportsNoCredentialsMessage=Realm ondersteunt geen enkel soort aanmeldgegeven.
+identityProviderNotUniqueMessage=Realm ondersteunt meerdere identity providers. Er kon niet bepaald worden welke identity provider er gebruikt zou moeten worden tijdens de authenticatie.
+emailVerifiedMessage=Uw e-mailadres is geverifieerd.
+staleEmailVerificationLink=De link die u gebruikt is verlopen, wellicht omdat u uw e-mailadres al eerder geverifieerd heeft.
+
+backToApplication=« Terug naar de applicatie
+missingParameterMessage=Missende parameters: {0}
+clientNotFoundMessage=Client niet gevonden.
+clientDisabledMessage=Client is inactief.
+invalidParameterMessage=Ongeldige parameter: {0}
+alreadyLoggedIn=U bent al ingelogd.
+
+p3pPolicy=CP="This is not a P3P policy!"
+fullName=Volledige naam
+street=Straat
+locality=Plaats
+region=Staat, provincie of regio
+emailLinkIdp4=Als u de e-mail al geverifieerd heeft in een andere browser
+emailLinkIdp5=om door te gaan.
+pageExpiredTitle=Pagina is verlopen
+pageExpiredMsg1=Om het inlogproces te herstarten
+pageExpiredMsg2=Om het inlogproces te vervolgen
+role_admin=Beheerder
+role_view-applications=Bekijk applicaties
+role_manage-applications=Beheer applicaties
+role_manage-account=Beheer account
+role_manage-account-links=Beheer account-links
+client_realm-management=Realm-beheer
+expiredActionMessage=Actie verlopen. Vervolg nu met inloggen.
+invalidPasswordGenericMessage=Ongeldig wachtwoord: het nieuwe wachtwoord voldoet niet aan het wachtwoordbeleid.
+identityProviderAlreadyLinkedMessage=De door {0} teruggegeven gefedereerde identiteit is al aan een andere gebruiker gekoppeld.
+differentUserAuthenticated=U bent in deze sessie al als de gebruiker "{0}" aangemeld. Log eerst uit.
+brokerLinkingSessionExpired=Broker account linking aangevraagd, maar de huidige sessie in verlopen.
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_no.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_no.properties
index 1f1a9d903e..47922cd277 100644
--- a/themes/src/main/resources-community/theme/base/login/messages/messages_no.properties
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_no.properties
@@ -214,6 +214,7 @@ locale_es=Espa\u00F1ol
locale_fr=Fran\u00e7ais
locale_it=Italian
locale_ja=\u65E5\u672C\u8A9E
+locale_nl=Nederlands
locale_no=Norsk
locale_pt_BR=Portugu\u00EAs (Brasil)
locale_pt-BR=Portugu\u00EAs (Brasil)
diff --git a/themes/src/main/resources-community/theme/base/login/theme.properties b/themes/src/main/resources-community/theme/base/login/theme.properties
index 6b2b6e8fac..f1aeaf5301 100644
--- a/themes/src/main/resources-community/theme/base/login/theme.properties
+++ b/themes/src/main/resources-community/theme/base/login/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru,sv
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,no,nl,pt-BR,ru,sv
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_en.properties b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
index 47dbda14ba..906c525ef2 100755
--- a/themes/src/main/resources/theme/base/account/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
@@ -160,9 +160,10 @@ locale_es=Espa\u00F1ol
locale_fr=Fran\u00e7ais
locale_it=Italian
locale_ja=\u65E5\u672C\u8A9E
+locale_nl=Nederlands
locale_no=Norsk
locale_lt=Lietuvi\u0173
locale_pt-BR=Portugu\u00EAs (Brasil)
locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
+locale_sv=Svenska
locale_zh-CN=\u4e2d\u6587\u7b80\u4f53
-locale_sv=Svenska
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_zh_CN.properties b/themes/src/main/resources/theme/base/account/messages/messages_zh_CN.properties
index 4691002972..f263668434 100644
--- a/themes/src/main/resources/theme/base/account/messages/messages_zh_CN.properties
+++ b/themes/src/main/resources/theme/base/account/messages/messages_zh_CN.properties
@@ -157,6 +157,7 @@ locale_es=Español
locale_fr=Français
locale_it=Italian
locale_ja=日本語
+locale_nl=Nederlands
locale_no=Norsk
locale_lt=Lietuvių
locale_pt-BR=Português (Brasil)
diff --git a/themes/src/main/resources/theme/base/account/theme.properties b/themes/src/main/resources/theme/base/account/theme.properties
index b9c3990957..d7c6edfc4d 100644
--- a/themes/src/main/resources/theme/base/account/theme.properties
+++ b/themes/src/main/resources/theme/base/account/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru,zh-CN
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,nl,no,pt-BR,ru,zh-CN
diff --git a/themes/src/main/resources/theme/base/admin/theme.properties b/themes/src/main/resources/theme/base/admin/theme.properties
index 4bd8da4d73..36d3234157 100644
--- a/themes/src/main/resources/theme/base/admin/theme.properties
+++ b/themes/src/main/resources/theme/base/admin/theme.properties
@@ -1,2 +1,2 @@
import=common/keycloak
-locales=ca,en,es,fr,it,ja,lt,no,pt-BR,ru,zh-CN
\ No newline at end of file
+locales=ca,en,es,fr,it,ja,lt,nl,no,pt-BR,ru,zh-CN
diff --git a/themes/src/main/resources/theme/base/email/theme.properties b/themes/src/main/resources/theme/base/email/theme.properties
index b9c3990957..d7c6edfc4d 100644
--- a/themes/src/main/resources/theme/base/email/theme.properties
+++ b/themes/src/main/resources/theme/base/email/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru,zh-CN
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,nl,no,pt-BR,ru,zh-CN
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_en.properties b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
index dbd0a3c340..9abb4feab4 100755
--- a/themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -230,6 +230,7 @@ locale_es=Espa\u00F1ol
locale_fr=Fran\u00e7ais
locale_it=Italian
locale_ja=\u65E5\u672C\u8A9E
+locale_nl=Nederlands
locale_no=Norsk
locale_pt_BR=Portugu\u00EAs (Brasil)
locale_pt-BR=Portugu\u00EAs (Brasil)
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_zh_CN.properties b/themes/src/main/resources/theme/base/login/messages/messages_zh_CN.properties
index 7a1a0728ba..39340bbef2 100644
--- a/themes/src/main/resources/theme/base/login/messages/messages_zh_CN.properties
+++ b/themes/src/main/resources/theme/base/login/messages/messages_zh_CN.properties
@@ -215,6 +215,7 @@ locale_es=Español
locale_fr=Français
locale_it=Italian
locale_ja=日本語
+locale_nl=Nederlands
locale_no=Norsk
locale_pt_BR=Português (Brasil)
locale_pt-BR=Português (Brasil)
diff --git a/themes/src/main/resources/theme/base/login/theme.properties b/themes/src/main/resources/theme/base/login/theme.properties
index b9c3990957..d7c6edfc4d 100644
--- a/themes/src/main/resources/theme/base/login/theme.properties
+++ b/themes/src/main/resources/theme/base/login/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,ja,lt,no,pt-BR,ru,zh-CN
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,lt,nl,no,pt-BR,ru,zh-CN
From ae54dd848d96893aca2d8e85d533a3be9962ff5d Mon Sep 17 00:00:00 2001
From: Stian Thorgersen
Date: Thu, 17 Aug 2017 13:15:41 +0200
Subject: [PATCH 05/26] KEYCLOAK-5185 (#4392)
---
distribution/server-overlay/src/main/modules/layers.conf | 1 +
1 file changed, 1 insertion(+)
create mode 100644 distribution/server-overlay/src/main/modules/layers.conf
diff --git a/distribution/server-overlay/src/main/modules/layers.conf b/distribution/server-overlay/src/main/modules/layers.conf
new file mode 100644
index 0000000000..74f44850c7
--- /dev/null
+++ b/distribution/server-overlay/src/main/modules/layers.conf
@@ -0,0 +1 @@
+layers=keycloak
\ No newline at end of file
From efd44d86c546db22725fdfea3fed431bd7904e76 Mon Sep 17 00:00:00 2001
From: Stian Thorgersen
Date: Thu, 17 Aug 2017 14:40:29 +0200
Subject: [PATCH 06/26] KEYCLOAK-5263 (#4393)
---
distribution/demo-dist/src/main/xslt/standalone.xsl | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/distribution/demo-dist/src/main/xslt/standalone.xsl b/distribution/demo-dist/src/main/xslt/standalone.xsl
index 5ea7e93ce0..f800ae2359 100755
--- a/distribution/demo-dist/src/main/xslt/standalone.xsl
+++ b/distribution/demo-dist/src/main/xslt/standalone.xsl
@@ -17,10 +17,10 @@
From 0c21b8c3a61c61cf17e112c0168d0f4822220ad2 Mon Sep 17 00:00:00 2001
From: mhajas
Date: Fri, 28 Jul 2017 12:53:54 +0200
Subject: [PATCH 07/26] KEYCLOAK-4393 Remove example tests
---
.../adapter/page/BasicAuthExample.java | 61 ---
.../adapter/page/CustomerPortalExample.java | 101 -----
.../adapter/page/DatabaseServiceExample.java | 45 ---
.../adapter/page/MultiTenantExample.java | 64 ---
.../adapter/page/ProductPortalExample.java | 80 ----
.../adapter/page/SAMLPostEncExample.java | 51 ---
.../adapter/page/SAMLPostSigExample.java | 51 ---
.../adapter/page/SAMLRedirectSigExample.java | 51 ---
.../AbstractBasicAuthExampleAdapterTest.java | 89 -----
.../AbstractDemoExampleAdapterTest.java | 373 ------------------
.../AbstractSAMLExampleAdapterTest.java | 126 ------
.../EAPBasicAuthExampleAdapterTest.java | 12 -
.../example/EAPDemoExampleAdapterTest.java | 12 -
.../example/EAPSAMLExampleAdapterTest.java | 11 -
.../EAP6BasicAuthExampleAdapterTest.java | 12 -
.../example/EAP6DemoExampleAdapterTest.java | 12 -
.../example/EAP6SAMLExampleAdapterTest.java | 11 -
...elativeEAPBasicAuthExampleAdapterTest.java | 9 -
.../RelativeEAPCorsExampleAdapterTest.java | 9 -
.../RelativeEAPDemoExampleAdapterTest.java | 9 -
.../RelativeEAPSAMLExampleAdapterTest.java | 9 -
.../RemoteBasicAuthExampleAdapterTest.java | 12 -
.../example/RemoteDemoExampleAdapterTest.java | 12 -
.../example/RemoteSAMLExampleAdapterTest.java | 11 -
.../WildflyDemoExampleAdapterTest.java | 12 -
.../WildflySAMLExampleAdapterTest.java | 11 -
.../Wildfly10BasicAuthExampleAdapterTest.java | 12 -
.../Wildfly10DemoExampleAdapterTest.java | 12 -
.../Wildfly10SAMLExampleAdapterTest.java | 11 -
.../Wildfly8BasicAuthExampleAdapterTest.java | 12 -
.../Wildfly8DemoExampleAdapterTest.java | 12 -
.../Wildfly9BasicAuthExampleAdapterTest.java | 12 -
.../Wildfly9DemoExampleAdapterTest.java | 12 -
.../Wildfly9SAMLExampleAdapterTest.java | 11 -
.../tests/other/adapters/pom.xml | 60 ---
.../Tomcat7BasicAuthExampleAdapterTest.java | 12 -
.../Tomcat7DemoExampleAdapterTest.java | 12 -
.../Tomcat8BasicAuthExampleAdapterTest.java | 12 -
.../Tomcat8DemoExampleAdapterTest.java | 12 -
.../Tomcat9BasicAuthExampleAdapterTest.java | 12 -
.../Tomcat9DemoExampleAdapterTest.java | 12 -
41 files changed, 1482 deletions(-)
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuthExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/CustomerPortalExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/DatabaseServiceExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenantExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/ProductPortalExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostEncExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostSigExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLRedirectSigExample.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractBasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractSAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPBasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPDemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPSAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6DemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6SAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPBasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPCorsExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPDemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPSAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteBasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteDemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteSAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyDemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflySAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10DemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10SAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9DemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9SAMLExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7DemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DemoExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9BasicAuthExampleAdapterTest.java
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9DemoExampleAdapterTest.java
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuthExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuthExample.java
deleted file mode 100644
index 09774b69d0..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BasicAuthExample.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-
-import javax.ws.rs.core.UriBuilder;
-import java.net.URL;
-
-/**
- *
- * @author tkyjovsk
- */
-public class BasicAuthExample extends AbstractPageWithInjectedUrl {
-
- public static final String DEPLOYMENT_NAME = "basic-auth-example";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("basicauth");
- return fixedUrl != null ? fixedUrl : url;
- }
-
- @Override
- public UriBuilder createUriBuilder() {
- return super.createUriBuilder()
- .userInfo("{user}:{password}")
- .path("service/echo")
- .queryParam("value", "{value}");
- }
-
- public BasicAuthExample setTemplateValues(String user, String password, String value) {
- setUriParameter("user", user);
- setUriParameter("password", password);
- setUriParameter("value", value);
- return this;
- }
-
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/CustomerPortalExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/CustomerPortalExample.java
deleted file mode 100644
index 8f02dc609a..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/CustomerPortalExample.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.graphene.findby.FindByJQuery;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-import org.openqa.selenium.WebElement;
-
-import java.net.URL;
-
-import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
-
-/**
- *
- * @author tkyjovsk
- */
-public class CustomerPortalExample extends AbstractPageWithInjectedUrl {
-
- public static final String DEPLOYMENT_NAME = "customer-portal-example";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("customer-portal");
- return fixedUrl != null ? fixedUrl : url;
- }
-
- @FindByJQuery("h1:contains('Customer Portal')")
- private WebElement title;
-
- @FindByJQuery("a:contains('Customer Listing')")
- private WebElement customerListingLink;
- @FindByJQuery("h1:contains('Customer Listing')")
- private WebElement customerListingHeader;
-
- @FindByJQuery("h1:contains('Customer Session')")
- private WebElement customerSessionHeader;
-
- @FindByJQuery("a:contains('Customer Admin Interface')")
- private WebElement customerAdminInterfaceLink;
-
- @FindByJQuery("a:contains('Customer Session')")
- private WebElement customerSessionLink;
-
- @FindByJQuery("a:contains('products')")
- private WebElement productsLink;
-
- @FindByJQuery("a:contains('logout')")
- private WebElement logOutButton;
-
- public void goToProducts() {
- productsLink.click();
- }
-
- public void customerListing() {
- customerListingLink.click();
- }
-
- public void customerAdminInterface() {
- customerAdminInterfaceLink.click();
- }
-
- public void customerSession() {
- waitUntilElement(customerSessionLink).is().present();
- customerSessionLink.click();
- }
-
- public void logOut() {
- logOutButton.click();
- }
-
- public void waitForCustomerListingHeader() {
- waitUntilElement(customerListingHeader).is().not().present();
- }
-
- public void waitForCustomerSessionHeader() {
- waitUntilElement(customerSessionHeader).is().not().present();
- }
-
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/DatabaseServiceExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/DatabaseServiceExample.java
deleted file mode 100644
index c856064a9d..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/DatabaseServiceExample.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-
-import java.net.URL;
-
-/**
- *
- * @author tkyjovsk
- */
-public class DatabaseServiceExample extends AbstractPageWithInjectedUrl {
-
- public static final String DEPLOYMENT_NAME = "database-service-example";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("database");
- return fixedUrl != null ? fixedUrl : url;
- }
-
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenantExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenantExample.java
deleted file mode 100644
index 7cff7140d4..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenantExample.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-
-import javax.ws.rs.core.UriBuilder;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- *
- * @author tkyjovsk
- */
-public class MultiTenantExample extends AbstractPageWithInjectedUrl {
-
- public static final String DEPLOYMENT_NAME = "multi-tenant-example";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @Override
- public URL getInjectedUrl() {
- return url;
- }
-
- @Override
- public UriBuilder createUriBuilder() {
- return super.createUriBuilder().path("{tenantRealm}");
- }
-
- public URL getTenantRealmUrl(String realm) {
- try {
- return getUriBuilder().build(realm).toURL();
- } catch (MalformedURLException ex) {
- throw new IllegalStateException("Page URL is malformed.");
- }
- }
-
- public void navigateToRealm(String realm) {
- URL u = getTenantRealmUrl(realm);
- log.info("navigate to "+u.toExternalForm());
- driver.navigate().to(u.toExternalForm());
- }
-
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/ProductPortalExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/ProductPortalExample.java
deleted file mode 100644
index 81c8b0a0cb..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/ProductPortalExample.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.graphene.findby.FindByJQuery;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-import org.openqa.selenium.WebElement;
-
-import java.net.URL;
-
-import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
-
-/**
- *
- * @author tkyjovsk
- */
-public class ProductPortalExample extends AbstractPageWithInjectedUrl {
-
- public static final String DEPLOYMENT_NAME = "product-portal-example";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("product-portal");
- return fixedUrl != null ? fixedUrl : url;
- }
-
- @FindByJQuery("h1:contains('Product Portal')")
- private WebElement title;
-
- @FindByJQuery("a:contains('Product Listing')")
- private WebElement productListingLink;
- @FindByJQuery("h1:contains('Product Listing')")
- private WebElement productListingHeader;
-
- @FindByJQuery("a:contains('customers')")
- private WebElement customersLink;
-
- @FindByJQuery("a:contains('logout')")
- private WebElement logOutButton;
-
- public void productListing() {
- productListingLink.click();
- }
-
- public void goToCustomers() {
- customersLink.click();
- }
-
- public void waitForProductListingHeader() {
- waitUntilElement(productListingHeader).is().not().present();
- }
-
- public void logOut() {
- logOutButton.click();
- }
-
-
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostEncExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostEncExample.java
deleted file mode 100644
index 6772ea9d90..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostEncExample.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-
-import java.net.URL;
-
-/**
- * @author mhajas
- */
-public class SAMLPostEncExample extends AbstractPageWithInjectedUrl {
- public static final String DEPLOYMENT_NAME = "saml-post-encryption";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @FindBy(tagName = "a")
- WebElement logoutButton;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("sales-post-enc");
- return fixedUrl != null ? fixedUrl : url;
- }
-
- public void logout() {
- logoutButton.click();
- }
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostSigExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostSigExample.java
deleted file mode 100644
index 7105bd1a64..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLPostSigExample.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-
-import java.net.URL;
-
-/**
- * @author mhajas
- */
-public class SAMLPostSigExample extends AbstractPageWithInjectedUrl {
- public static final String DEPLOYMENT_NAME = "sales-post-sig";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @FindBy(tagName = "a")
- WebElement logoutButton;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("sales-post-sig");
- return fixedUrl != null ? fixedUrl : url;
- }
-
- public void logout() {
- logoutButton.click();
- }
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLRedirectSigExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLRedirectSigExample.java
deleted file mode 100644
index 78e1316a33..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLRedirectSigExample.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.page;
-
-import org.jboss.arquillian.container.test.api.OperateOnDeployment;
-import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.FindBy;
-
-import java.net.URL;
-
-/**
- * @author mhajas
- */
-public class SAMLRedirectSigExample extends AbstractPageWithInjectedUrl {
- public static final String DEPLOYMENT_NAME = "saml-redirect-signatures";
-
- @ArquillianResource
- @OperateOnDeployment(DEPLOYMENT_NAME)
- private URL url;
-
- @FindBy(tagName = "a")
- WebElement logoutButton;
-
- @Override
- public URL getInjectedUrl() {
- //EAP6 URL fix
- URL fixedUrl = createInjectedURL("employee-sig");
- return fixedUrl != null ? fixedUrl : url;
- }
-
- public void logout() {
- logoutButton.click();
- }
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractBasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractBasicAuthExampleAdapterTest.java
deleted file mode 100644
index 57868f28be..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractBasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.example;
-
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.graphene.page.Page;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.Test;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
-import org.keycloak.testsuite.adapter.page.BasicAuthExample;
-
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.core.Response;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.keycloak.testsuite.auth.page.AuthRealm.EXAMPLE;
-import static org.keycloak.testsuite.util.IOUtil.loadRealm;
-
-public abstract class AbstractBasicAuthExampleAdapterTest extends AbstractExampleAdapterTest {
-
- @Page
- private BasicAuthExample basicAuthExample;
-
- @Deployment(name = BasicAuthExample.DEPLOYMENT_NAME)
- private static WebArchive basicAuthExample() throws IOException {
- return exampleDeployment("examples-basicauth");
- }
-
- @Override
- public void addAdapterTestRealms(List testRealms) {
- testRealms.add(loadRealm(new File(EXAMPLES_HOME_DIR + "/basic-auth/basicauthrealm.json")));
- }
-
- @Override
- public void setDefaultPageUriParameters() {
- super.setDefaultPageUriParameters();
- testRealmPage.setAuthRealm(EXAMPLE);
- }
-
- @Test
- public void testBasicAuthExample() {
- String value = "hello";
- Client client = ClientBuilder.newClient();
-
- Response response = client.target(basicAuthExample
- .setTemplateValues("admin", "password", value).buildUri()).request().get();
- assertEquals(200, response.getStatus());
- assertEquals(value, response.readEntity(String.class));
- response.close();
-
- response = client.target(basicAuthExample
- .setTemplateValues("invalid-user", "password", value).buildUri()).request().get();
- assertEquals(401, response.getStatus());
- String readResponse = response.readEntity(String.class);
- assertTrue(readResponse.contains("Unauthorized") || readResponse.contains("Status 401"));
- response.close();
-
- response = client.target(basicAuthExample
- .setTemplateValues("admin", "invalid-password", value).buildUri()).request().get();
- assertEquals(401, response.getStatus());
- readResponse = response.readEntity(String.class);
- assertTrue(readResponse.contains("Unauthorized") || readResponse.contains("Status 401"));
- response.close();
-
- client.close();
- }
-
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java
deleted file mode 100644
index 4db4a3c46a..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractDemoExampleAdapterTest.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.example;
-
-import org.apache.commons.io.FileUtils;
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.graphene.page.Page;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.keycloak.admin.client.resource.ClientResource;
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
-import org.keycloak.testsuite.adapter.page.CustomerPortalExample;
-import org.keycloak.testsuite.adapter.page.DatabaseServiceExample;
-import org.keycloak.testsuite.adapter.page.ProductPortalExample;
-import org.keycloak.testsuite.admin.ApiUtil;
-import org.keycloak.testsuite.auth.page.account.Account;
-import org.keycloak.testsuite.auth.page.account.Applications;
-import org.keycloak.testsuite.auth.page.login.OAuthGrant;
-import org.keycloak.testsuite.console.page.events.Config;
-import org.keycloak.testsuite.console.page.events.LoginEvents;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
-import static org.keycloak.testsuite.util.IOUtil.loadRealm;
-import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
-
-public abstract class AbstractDemoExampleAdapterTest extends AbstractExampleAdapterTest {
-
- @Page
- private CustomerPortalExample customerPortalExamplePage;
-
- @Page
- private ProductPortalExample productPortalExamplePage;
-
- @Page
- private DatabaseServiceExample databaseServiceExamplePage;
-
- @Page
- private Account testRealmAccountPage;
-
- @Page
- private Config configPage;
-
- @Page
- private LoginEvents loginEventsPage;
-
- @Page
- private OAuthGrant oAuthGrantPage;
-
- @Page
- private Applications applicationsPage;
-
- @Deployment(name = CustomerPortalExample.DEPLOYMENT_NAME)
- private static WebArchive customerPortalExample() throws IOException {
- return exampleDeployment(CustomerPortalExample.DEPLOYMENT_NAME);
- }
-
- @Deployment(name = ProductPortalExample.DEPLOYMENT_NAME)
- private static WebArchive productPortalExample() throws IOException {
- return exampleDeployment(ProductPortalExample.DEPLOYMENT_NAME);
- }
-
- @Deployment(name = DatabaseServiceExample.DEPLOYMENT_NAME)
- private static WebArchive databaseServiceExample() throws IOException {
- return exampleDeployment("database-service");
- }
-
- @Override
- public void addAdapterTestRealms(List testRealms) {
- testRealms.add(
- loadRealm(new File(EXAMPLES_HOME_DIR + "/demo-template/testrealm.json")));
- }
-
- @Override
- public void setDefaultPageUriParameters() {
- super.setDefaultPageUriParameters();
- testRealmPage.setAuthRealm(DEMO);
- testRealmLoginPage.setAuthRealm(DEMO);
- testRealmAccountPage.setAuthRealm(DEMO);
- configPage.setConsoleRealm(DEMO);
- loginEventsPage.setConsoleRealm(DEMO);
- applicationsPage.setAuthRealm(DEMO);
- }
-
- @Before
- public void beforeDemoExampleTest() {
- customerPortalExamplePage.navigateTo();
- driver.manage().deleteAllCookies();
- productPortalExamplePage.navigateTo();
- driver.manage().deleteAllCookies();
- }
-
- @Test
- public void customerPortalListingTest() {
-
- customerPortalExamplePage.navigateTo();
- customerPortalExamplePage.customerListing();
-
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- assertCurrentUrlStartsWith(customerPortalExamplePage);
- customerPortalExamplePage.waitForCustomerListingHeader();
-
- Assert.assertTrue(driver.getPageSource().contains("Username: bburke@redhat.com"));
- Assert.assertTrue(driver.getPageSource().contains("Bill Burke"));
- Assert.assertTrue(driver.getPageSource().contains("Stian Thorgersen"));
- }
-
- @Test
- public void customerPortalSessionTest() {
-
- customerPortalExamplePage.navigateTo();
- customerPortalExamplePage.customerSession();
-
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- assertCurrentUrlStartsWith(customerPortalExamplePage);
-
- customerPortalExamplePage.waitForCustomerSessionHeader();
- Assert.assertTrue(driver.getPageSource().contains("You visited this page"));
- }
-
- @Test
- public void productPortalListingTest() {
-
- productPortalExamplePage.navigateTo();
- productPortalExamplePage.productListing();
-
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- assertCurrentUrlStartsWith(productPortalExamplePage);
- productPortalExamplePage.waitForProductListingHeader();
-
- Assert.assertTrue(driver.getPageSource().contains("iphone"));
- Assert.assertTrue(driver.getPageSource().contains("ipad"));
- Assert.assertTrue(driver.getPageSource().contains("ipod"));
-
- productPortalExamplePage.goToCustomers();
- }
-
- @Test
- public void goToProductPortalWithOneLoginTest() {
-
- productPortalExamplePage.navigateTo();
- productPortalExamplePage.productListing();
-
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- assertCurrentUrlStartsWith(productPortalExamplePage);
- productPortalExamplePage.waitForProductListingHeader();
- productPortalExamplePage.goToCustomers();
-
- assertCurrentUrlStartsWith(customerPortalExamplePage);
- customerPortalExamplePage.customerListing();
- customerPortalExamplePage.goToProducts();
- assertCurrentUrlStartsWith(productPortalExamplePage);
- }
-
- @Test
- public void logoutFromAllAppsTest() {
-
- productPortalExamplePage.navigateTo();
- productPortalExamplePage.productListing();
-
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- assertCurrentUrlStartsWith(productPortalExamplePage);
- productPortalExamplePage.waitForProductListingHeader();
-
- if (isRelative()) { //KEYCLOAK-1546
- productPortalExamplePage.logOut();
- } else {
- driver.navigate().to(testRealmPage.getOIDCLogoutUrl() + "?redirect_uri=" + productPortalExamplePage);
- }
-
- assertCurrentUrlStartsWith(productPortalExamplePage);
- productPortalExamplePage.productListing();
-
- customerPortalExamplePage.navigateTo();
- customerPortalExamplePage.customerListing();
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- customerPortalExamplePage.logOut();
- }
-
- @Test
- public void grantServerBasedApp() {
- ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "customer-portal");
- ClientRepresentation client = clientResource.toRepresentation();
- client.setConsentRequired(true);
- clientResource.update(client);
-
- RealmRepresentation realm = testRealmResource().toRepresentation();
- realm.setEventsEnabled(true);
- realm.setEnabledEventTypes(Arrays.asList("REVOKE_GRANT", "LOGIN"));
- testRealmResource().update(realm);
-
- customerPortalExamplePage.navigateTo();
- customerPortalExamplePage.customerSession();
-
- loginPage.form().login("bburke@redhat.com", "password");
-
- assertTrue(oAuthGrantPage.isCurrent());
-
- oAuthGrantPage.accept();
-
- assertTrue(driver.getPageSource().contains("Your hostname:"));
- assertTrue(driver.getPageSource().contains("You visited this page"));
-
- applicationsPage.navigateTo();
- applicationsPage.revokeGrantForApplication("customer-portal");
-
- customerPortalExamplePage.navigateTo();
- customerPortalExamplePage.customerSession();
-
- assertTrue(oAuthGrantPage.isCurrent());
-
- loginEventsPage.navigateTo();
- if (!testContext.isAdminLoggedIn()) {
- loginPage.form().login(adminUser);
- testContext.setAdminLoggedIn(true);
- }
- loginEventsPage.table().filter();
- loginEventsPage.table().filterForm().addEventType("REVOKE_GRANT");
- loginEventsPage.table().update();
-
- List resultList = loginEventsPage.table().rows();
-
- assertEquals(1, resultList.size());
-
- resultList.get(0).findElement(By.xpath(".//td[text()='REVOKE_GRANT']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='account']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='revoked_client']/../td[text()='customer-portal']"));
-
- loginEventsPage.table().reset();
- loginEventsPage.table().filterForm().addEventType("LOGIN");
- loginEventsPage.table().update();
- resultList = loginEventsPage.table().rows();
-
- assertEquals(1, resultList.size());
-
- resultList.get(0).findElement(By.xpath(".//td[text()='LOGIN']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='customer-portal']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='username']/../td[text()='bburke@redhat.com']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='consent']/../td[text()='consent_granted']"));
- }
-
- @Test
- public void historyOfAccessResourceTest() throws IOException {
- RealmRepresentation realm = testRealmResource().toRepresentation();
- realm.setEventsEnabled(true);
- realm.setEnabledEventTypes(Arrays.asList("LOGIN", "LOGIN_ERROR", "LOGOUT", "CODE_TO_TOKEN"));
- testRealmResource().update(realm);
-
- customerPortalExamplePage.navigateTo();
- customerPortalExamplePage.customerListing();
-
- testRealmLoginPage.form().login("bburke@redhat.com", "password");
-
- Assert.assertTrue(driver.getPageSource().contains("Username: bburke@redhat.com")
- && driver.getPageSource().contains("Bill Burke")
- && driver.getPageSource().contains("Stian Thorgersen")
- );
-
- if (isRelative()) { //KEYCLOAK-1546
- productPortalExamplePage.logOut();
- } else {
- driver.navigate().to(testRealmPage.getOIDCLogoutUrl() + "?redirect_uri=" + productPortalExamplePage);
- }
-
- loginEventsPage.navigateTo();
-
- if (!testContext.isAdminLoggedIn()) {
- loginPage.form().login(adminUser);
- testContext.setAdminLoggedIn(true);
- }
-
- loginEventsPage.table().filter();
- loginEventsPage.table().filterForm().addEventType("LOGOUT");
- loginEventsPage.table().update();
-
- List resultList = loginEventsPage.table().rows();
-
- assertEquals(1, resultList.size());
-
- resultList.get(0).findElement(By.xpath(".//td[text()='LOGOUT']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
-
- loginEventsPage.table().reset();
- loginEventsPage.table().filterForm().addEventType("LOGIN");
- loginEventsPage.table().update();
- resultList = loginEventsPage.table().rows();
-
- assertEquals(1, resultList.size());
-
- resultList.get(0).findElement(By.xpath(".//td[text()='LOGIN']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='customer-portal']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='username']/../td[text()='bburke@redhat.com']"));
-
- loginEventsPage.table().reset();
- loginEventsPage.table().filterForm().addEventType("CODE_TO_TOKEN");
- loginEventsPage.table().update();
- resultList = loginEventsPage.table().rows();
-
- assertEquals(1, resultList.size());
- resultList.get(0).findElement(By.xpath(".//td[text()='CODE_TO_TOKEN']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='customer-portal']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
- resultList.get(0).findElement(By.xpath(".//td[text()='refresh_token_type']/../td[text()='Refresh']"));
-
- String serverLogPath = null;
-
- if (System.getProperty("app.server").equals("wildfly") || System.getProperty("app.server").equals("eap6") || System.getProperty("app.server").equals("eap")) {
- serverLogPath = System.getProperty("app.server.home") + "/standalone/log/server.log";
- }
-
- String appServerUrl;
- if (Boolean.parseBoolean(System.getProperty("app.server.ssl.required"))) {
- appServerUrl = "https://localhost:" + System.getProperty("app.server.https.port", "8543") + "/";
- } else {
- appServerUrl = "http://localhost:" + System.getProperty("app.server.http.port", "8280") + "/";
- }
-
- if (serverLogPath != null) {
- log.info("Checking app server log at: " + serverLogPath);
- File serverLog = new File(serverLogPath);
- String serverLogContent = FileUtils.readFileToString(serverLog);
- UserRepresentation bburke = ApiUtil.findUserByUsername(testRealmResource(), "bburke@redhat.com");
-
- Pattern pattern = Pattern.compile("User '" + bburke.getId() + "' invoking '" + appServerUrl + "customer-portal\\/customers\\/view\\.jsp[^\\s]+' on client 'customer-portal'");
- Matcher matcher = pattern.matcher(serverLogContent);
-
- assertTrue(matcher.find());
- assertTrue(serverLogContent.contains("User '" + bburke.getId() + "' invoking '" + appServerUrl + "database/customers' on client 'database-service'"));
- } else {
- log.info("Checking app server log on app-server: \"" + System.getProperty("app.server") + "\" is not supported.");
- }
- }
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractSAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractSAMLExampleAdapterTest.java
deleted file mode 100644
index 3a0676e499..0000000000
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractSAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.testsuite.adapter.example;
-
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.graphene.page.Page;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.Test;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
-import org.keycloak.testsuite.adapter.page.SAMLPostEncExample;
-import org.keycloak.testsuite.adapter.page.SAMLPostSigExample;
-import org.keycloak.testsuite.adapter.page.SAMLRedirectSigExample;
-import org.keycloak.testsuite.util.URLAssert;
-import org.openqa.selenium.By;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-import static org.keycloak.testsuite.auth.page.AuthRealm.SAMLDEMO;
-import static org.keycloak.testsuite.util.IOUtil.loadRealm;
-import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
-
-/**
- * @author mhajas
- */
-public abstract class AbstractSAMLExampleAdapterTest extends AbstractExampleAdapterTest {
-
- @Page
- private SAMLPostSigExample samlPostSigExamplePage;
-
- @Page
- private SAMLPostEncExample samlPostEncExamplePage;
-
- @Page
- private SAMLRedirectSigExample samlRedirectSigExamplePage;
-
- @Override
- public void addAdapterTestRealms(List testRealms) {
- RealmRepresentation samlRealm = loadRealm(new File(EXAMPLES_HOME_DIR + "/saml/testsaml.json"));
- testRealms.add(samlRealm);
- }
-
- @Override
- public void setDefaultPageUriParameters() {
- super.setDefaultPageUriParameters();
- testRealmPage.setAuthRealm(SAMLDEMO);
- testRealmSAMLRedirectLoginPage.setAuthRealm(SAMLDEMO);
- testRealmSAMLPostLoginPage.setAuthRealm(SAMLDEMO);
- }
-
- @Deployment(name = SAMLPostSigExample.DEPLOYMENT_NAME)
- private static WebArchive samlPostSigExampleDeployment() throws IOException {
- return exampleDeployment(SAMLPostSigExample.DEPLOYMENT_NAME);
- }
-
- @Deployment(name = SAMLPostEncExample.DEPLOYMENT_NAME)
- private static WebArchive samlPostEncExampleDeployment() throws IOException {
- return exampleDeployment(SAMLPostEncExample.DEPLOYMENT_NAME);
- }
-
- @Deployment(name = SAMLRedirectSigExample.DEPLOYMENT_NAME)
- private static WebArchive samlRedirectSigExampleDeployment() throws IOException {
- return exampleDeployment(SAMLRedirectSigExample.DEPLOYMENT_NAME);
- }
-
- @Test
- public void samlPostWithSignatureExampleTest() {
- samlPostSigExamplePage.navigateTo();
- testRealmSAMLPostLoginPage.form().login(bburkeUser);
-
- waitUntilElement(By.xpath("//body")).text().contains("Welcome to the Sales Tool, " + bburkeUser.getUsername());
-
- samlPostSigExamplePage.logout();
- waitUntilElement(By.xpath("//body")).text().contains("Logged out.");
-
- samlPostSigExamplePage.navigateTo();
- URLAssert.assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
- }
-
- @Test
- public void samlPostWithEncryptionExampleTest() {
- samlPostEncExamplePage.navigateTo();
-
- testRealmSAMLPostLoginPage.form().login(bburkeUser);
-
- waitUntilElement(By.xpath("//body")).text().contains("Welcome to the Sales Tool, " + bburkeUser.getUsername());
-
- samlPostEncExamplePage.logout();
- waitUntilElement(By.xpath("//body")).text().contains("Logged out.");
-
- samlPostEncExamplePage.navigateTo();
- URLAssert.assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
- }
-
- @Test
- public void samlRedirectWithSignatureExampleTest() {
- samlRedirectSigExamplePage.navigateTo();
-
- testRealmSAMLRedirectLoginPage.form().login(bburkeUser);
-
- waitUntilElement(By.xpath("//body")).text().contains("Welcome to the Employee Tool,");
-
- samlRedirectSigExamplePage.logout();
- URLAssert.assertCurrentUrlStartsWith(testRealmSAMLRedirectLoginPage);
-
- samlRedirectSigExamplePage.navigateTo();
- URLAssert.assertCurrentUrlStartsWith(testRealmSAMLRedirectLoginPage);
- }
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPBasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPBasicAuthExampleAdapterTest.java
deleted file mode 100644
index 574ee16c4c..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPBasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-eap")
-public class EAPBasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPDemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPDemoExampleAdapterTest.java
deleted file mode 100644
index f461222e5e..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPDemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-eap")
-public class EAPDemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPSAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPSAMLExampleAdapterTest.java
deleted file mode 100644
index b5431ff7b8..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPSAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- * @author mhajas
- */
-@AppServerContainer("app-server-eap")
-public class EAPSAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6BasicAuthExampleAdapterTest.java
deleted file mode 100644
index 8299093dc2..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-eap6")
-public class EAP6BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6DemoExampleAdapterTest.java
deleted file mode 100644
index d0c0c95e74..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-eap6")
-public class EAP6DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6SAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6SAMLExampleAdapterTest.java
deleted file mode 100644
index 208d43098e..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6SAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- * @author mhajas
- */
-@AppServerContainer("app-server-eap6")
-public class EAP6SAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPBasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPBasicAuthExampleAdapterTest.java
deleted file mode 100644
index 9d779502d2..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPBasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-/**
- *
- * @author tkyjovsk
- */
-public class RelativeEAPBasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPCorsExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPCorsExampleAdapterTest.java
deleted file mode 100644
index b96ee75e0f..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPCorsExampleAdapterTest.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-/**
- *
- * @author fkiss
- */
-public class RelativeEAPCorsExampleAdapterTest extends AbstractCorsExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPDemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPDemoExampleAdapterTest.java
deleted file mode 100644
index ef94eee5b3..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPDemoExampleAdapterTest.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-/**
- *
- * @author tkyjovsk
- */
-public class RelativeEAPDemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPSAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPSAMLExampleAdapterTest.java
deleted file mode 100644
index 2afe2381e1..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/src/test/java/org/keycloak/testsuite/adapter/example/RelativeEAPSAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-/**
- *
- * @author mhajas
- */
-public class RelativeEAPSAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteBasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteBasicAuthExampleAdapterTest.java
deleted file mode 100644
index 07b907e21a..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteBasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-remote")
-public class RemoteBasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteDemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteDemoExampleAdapterTest.java
deleted file mode 100644
index 90860d24e5..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteDemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-remote")
-public class RemoteDemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteSAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteSAMLExampleAdapterTest.java
deleted file mode 100644
index 9dca78baf0..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/remote/src/test/java/org/keycloak/testsuite/adapter/example/RemoteSAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- * @author mhajas
- */
-@AppServerContainer("app-server-remote")
-public class RemoteSAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyDemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyDemoExampleAdapterTest.java
deleted file mode 100644
index 588c28d82d..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyDemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly")
-public class WildflyDemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflySAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflySAMLExampleAdapterTest.java
deleted file mode 100644
index e118da1f1b..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflySAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- * @author mhajas
- */
-@AppServerContainer("app-server-wildfly")
-public class WildflySAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10BasicAuthExampleAdapterTest.java
deleted file mode 100644
index f49dd19949..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly10")
-public class Wildfly10BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10DemoExampleAdapterTest.java
deleted file mode 100644
index 6117bfd86e..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly10")
-public class Wildfly10DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10SAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10SAMLExampleAdapterTest.java
deleted file mode 100644
index d7a162c927..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly10/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly10SAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- * @author mhajas
- */
-@AppServerContainer("app-server-wildfly10")
-public class Wildfly10SAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8BasicAuthExampleAdapterTest.java
deleted file mode 100644
index dc4e7cc76c..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly8")
-public class Wildfly8BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DemoExampleAdapterTest.java
deleted file mode 100644
index 8bb20d8b67..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly8")
-public class Wildfly8DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9BasicAuthExampleAdapterTest.java
deleted file mode 100644
index 9d68c8a383..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly9")
-public class Wildfly9BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9DemoExampleAdapterTest.java
deleted file mode 100644
index 26ce953a62..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly9")
-public class Wildfly9DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9SAMLExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9SAMLExampleAdapterTest.java
deleted file mode 100644
index e5e5c27dab..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly9SAMLExampleAdapterTest.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- * @author mhajas
- */
-@AppServerContainer("app-server-wildfly9")
-public class Wildfly9SAMLExampleAdapterTest extends AbstractSAMLExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
index 6cfc621f24..bf67275f56 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
@@ -265,24 +265,6 @@
-
- org.keycloak.example.demo
- product-portal-example
- ${project.version}
- war
-
-
- org.keycloak.example.demo
- customer-portal-example
- ${project.version}
- war
-
-
- org.keycloak.example.demo
- database-service
- ${project.version}
- war
- org.keycloak.testsuiteintegration-arquillian-test-apps-js-console
@@ -295,48 +277,6 @@
${project.version}war
-
- org.keycloak
- examples-multitenant
- ${project.version}
- war
-
-
- org.keycloak
- examples-basicauth
- ${project.version}
- war
-
-
- org.keycloak.example.demo
- cors-angular-product-example
- ${project.version}
- war
-
-
- org.keycloak.example.demo
- cors-database-service
- ${project.version}
- war
-
-
- org.keycloak
- sales-post-sig
- ${project.version}
- war
-
-
- org.keycloak
- saml-post-encryption
- ${project.version}
- war
-
-
- org.keycloak
- saml-redirect-signatures
- ${project.version}
- war
- org.keycloak.testsuitehello-world-authz-service
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7BasicAuthExampleAdapterTest.java
deleted file mode 100644
index cd1e26b6b4..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-tomcat7")
-public class Tomcat7BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7DemoExampleAdapterTest.java
deleted file mode 100644
index cbfd42756e..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat7DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-tomcat7")
-public class Tomcat7DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8BasicAuthExampleAdapterTest.java
deleted file mode 100644
index 175ed9ef1a..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-tomcat8")
-public class Tomcat8BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DemoExampleAdapterTest.java
deleted file mode 100644
index ef3d06d0a4..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-tomcat8")
-public class Tomcat8DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9BasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9BasicAuthExampleAdapterTest.java
deleted file mode 100644
index 221c006761..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9BasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-tomcat9")
-public class Tomcat9BasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9DemoExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9DemoExampleAdapterTest.java
deleted file mode 100644
index 56ae537146..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat9DemoExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-tomcat9")
-public class Tomcat9DemoExampleAdapterTest extends AbstractDemoExampleAdapterTest {
-
-}
\ No newline at end of file
From d58499acfb0d0e71e43798835d1dfbf17da0ce7c Mon Sep 17 00:00:00 2001
From: mhajas
Date: Mon, 14 Aug 2017 12:03:22 +0200
Subject: [PATCH 08/26] KEYCLOAK-5311 Fix authorization tests
---
.../AbstractPhotozExampleAdapterTest.java | 15 +++++++--------
.../authorization/EAPServletAuthzAdapterTest.java | 3 +--
.../tests/other/adapters/pom.xml | 2 ++
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
index 2f9fede0ac..7223b2abcf 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
@@ -88,13 +88,6 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
@Before
public void beforePhotozExampleAdapterTest() throws FileNotFoundException {
deleteAllCookiesForClientPage();
-
- for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
- if ("Only Owner Policy".equals(policy.getName())) {
- policy.getConfig().put("mavenArtifactVersion", System.getProperty("project.version"));
- getAuthorizationResource().policies().policy(policy.getId()).update(policy);
- }
- }
}
@Override
@@ -650,7 +643,13 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
}
private void importResourceServerSettings() throws FileNotFoundException {
- getAuthorizationResource().importSettings(loadJson(new FileInputStream(new File(TEST_APPS_HOME_DIR + "/photoz/photoz-restful-api-authz-service.json")), ResourceServerRepresentation.class));
+ ResourceServerRepresentation authSettings = loadJson(new FileInputStream(new File(TEST_APPS_HOME_DIR + "/photoz/photoz-restful-api-authz-service.json")), ResourceServerRepresentation.class);
+
+ authSettings.getPolicies().stream()
+ .filter(x -> "Only Owner Policy".equals(x.getName()))
+ .forEach(x -> x.getConfig().put("mavenArtifactVersion", System.getProperty("project.version")));
+
+ getAuthorizationResource().importSettings(authSettings);
}
private AuthorizationResource getAuthorizationResource() throws FileNotFoundException {
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java
index 8355037f1c..0ff9905fd8 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EAPServletAuthzAdapterTest.java
@@ -17,7 +17,6 @@
package org.keycloak.testsuite.adapter.example.authorization;
import org.jboss.arquillian.container.test.api.RunAsClient;
-import org.keycloak.testsuite.adapter.example.authorization.AbstractServletAuthzAdapterTest;
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
/**
@@ -27,6 +26,6 @@ import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
@RunAsClient
@AppServerContainer("app-server-eap")
//@AdapterLibsLocationProperty("adapter.libs.wildfly")
-public class EAPServletAuthzAdapterTest extends AbstractServletAuthzAdapterTest {
+public class EAPServletAuthzAdapterTest extends AbstractServletAuthzFunctionalAdapterTest {
}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
index 6cfc621f24..8250a34dde 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
@@ -68,6 +68,7 @@
10399
+
@@ -81,6 +82,7 @@
-Djava.security.krb5.conf=${project.build.directory}/dependency/kerberos/test-krb5.conf
-Dkie.maven.settings.custom=${settings.path}
-Drepo.url=${repo.url}
+ -Dmaven.repo.local=${maven.repo.local}
${containers.home}/app-server-${app.server}
From a6a6a62dc03cb07e08b28d72dcfbad83f866e614 Mon Sep 17 00:00:00 2001
From: mposolda
Date: Fri, 18 Aug 2017 11:08:51 +0200
Subject: [PATCH 09/26] KEYCLOAK-5260 kc_idp_hint was only working first time
---
.../protocol/AuthorizationEndpointBase.java | 12 ++++-
.../oidc/endpoints/AuthorizationEndpoint.java | 45 ++++++++++++++++++-
.../broker/IdentityProviderHintTest.java | 23 ++++++++++
3 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index c06caa0737..b854e52cd9 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -180,9 +180,10 @@ public abstract class AuthorizationEndpointBase {
return new AuthorizationEndpointChecks(authSession);
} else if (isNewRequest(authSession, client, requestState)) {
- // Check if we have lastProcessedExecution and restart the session just if yes. Otherwise update just client information from the AuthorizationEndpoint request.
+ // Check if we have lastProcessedExecution note or if some request parameter beside state (eg. prompt, kc_idp_hint) changed. Restart the session just if yes.
+ // Otherwise update just client information from the AuthorizationEndpoint request.
// This difference is needed, because of logout from JS applications in multiple browser tabs.
- if (hasProcessedExecution(authSession)) {
+ if (shouldRestartAuthSession(authSession)) {
logger.debug("New request from application received, but authentication session already exists. Restart existing authentication session");
authSession.restartSession(realm, client);
} else {
@@ -223,11 +224,18 @@ public abstract class AuthorizationEndpointBase {
}
+
+ protected boolean shouldRestartAuthSession(AuthenticationSessionModel authSession) {
+ return hasProcessedExecution(authSession);
+ }
+
+
private boolean hasProcessedExecution(AuthenticationSessionModel authSession) {
String lastProcessedExecution = authSession.getAuthNote(AuthenticationProcessor.LAST_PROCESSED_EXECUTION);
return (lastProcessedExecution != null);
}
+
// See if we have lastProcessedExecution note. If yes, we are expired. Also if we are in different flow than initial one. Otherwise it is browser refresh of initial username/password form
private boolean shouldShowExpirePage(AuthenticationSessionModel authSession) {
if (hasProcessedExecution(authSession)) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 38dbc8f5e4..f00c89237d 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -49,6 +49,8 @@ import org.keycloak.util.TokenUtil;
import javax.ws.rs.GET;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
+
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -370,7 +372,48 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
// If state is same, we likely have the refresh of some previous request
String stateFromSession = authSession.getClientNote(OIDCLoginProtocol.STATE_PARAM);
- return !stateFromRequest.equals(stateFromSession);
+ boolean stateChanged =!stateFromRequest.equals(stateFromSession);
+ if (stateChanged) {
+ return true;
+ }
+
+ return isOIDCAuthenticationRelatedParamsChanged(authSession);
+ }
+
+
+ @Override
+ protected boolean shouldRestartAuthSession(AuthenticationSessionModel authSession) {
+ return super.shouldRestartAuthSession(authSession) || isOIDCAuthenticationRelatedParamsChanged(authSession);
+ }
+
+
+ // Check if some important OIDC parameters, which have impact on authentication, changed. If yes, we need to restart auth session
+ private boolean isOIDCAuthenticationRelatedParamsChanged(AuthenticationSessionModel authSession) {
+ if (isRequestParamChanged(authSession, OIDCLoginProtocol.LOGIN_HINT_PARAM, request.getLoginHint())) {
+ return true;
+ }
+ if (isRequestParamChanged(authSession, OIDCLoginProtocol.PROMPT_PARAM, request.getPrompt())) {
+ return true;
+ }
+ if (isRequestParamChanged(authSession, AdapterConstants.KC_IDP_HINT, request.getIdpHint())) {
+ return true;
+ }
+
+ String maxAgeValue = authSession.getClientNote(OIDCLoginProtocol.MAX_AGE_PARAM);
+ if (maxAgeValue == null && request.getMaxAge() == null) {
+ return false;
+ }
+ if (maxAgeValue != null && Integer.parseInt(maxAgeValue) == request.getMaxAge()) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ private boolean isRequestParamChanged(AuthenticationSessionModel authSession, String noteName, String requestParamValue) {
+ String authSessionNoteValue = authSession.getClientNote(noteName);
+ return !Objects.equals(authSessionNoteValue, requestParamValue);
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
index 05d1afa116..a58b82f257 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
@@ -95,6 +95,29 @@ public class IdentityProviderHintTest {
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
}
+
+ // KEYCLOAK-5260
+ @Test
+ public void testSuccessfulRedirectToProviderAfterLoginPageShown() {
+ this.driver.navigate().to("http://localhost:8081/test-app");
+ String loginPageUrl = driver.getCurrentUrl();
+ assertTrue(loginPageUrl.startsWith("http://localhost:8081/auth/"));
+
+ // Manually add "kc_idp_hint" to URL . Should redirect to provider
+ loginPageUrl = loginPageUrl + "&kc_idp_hint=kc-oidc-idp-hidden";
+ this.driver.navigate().to(loginPageUrl);
+ assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
+
+ // Redirect from the app with the "kc_idp_hint". Should redirect to provider
+ this.driver.navigate().to("http://localhost:8081/test-app?kc_idp_hint=kc-oidc-idp-hidden");
+ assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
+
+ // Now redirect should't happen
+ this.driver.navigate().to("http://localhost:8081/test-app");
+ assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/"));
+ }
+
+
@Test
public void testInvalidIdentityProviderHint() {
this.driver.navigate().to("http://localhost:8081/test-app?kc_idp_hint=invalid-idp-id");
From 7f7c0bac1efa2d9a68aabf99f93e7376b7a3a6c2 Mon Sep 17 00:00:00 2001
From: mhajas
Date: Mon, 21 Aug 2017 10:15:54 +0200
Subject: [PATCH 10/26] KEYCLOAK-5265 Set localization tests to community
profile only
---
.../java/org/keycloak/testsuite/i18n/LoginPageTest.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java
index 2d927198b6..ea3793a64d 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java
@@ -81,6 +81,8 @@ public class LoginPageTest extends AbstractI18NTest {
@Test
public void languageDropdown() {
+ ProfileAssume.assumeCommunity();
+
loginPage.open();
Assert.assertEquals("English", loginPage.getLanguageDropdownText());
@@ -143,6 +145,8 @@ public class LoginPageTest extends AbstractI18NTest {
// KEYCLOAK-3887
@Test
public void languageChangeRequiredActions() {
+ ProfileAssume.assumeCommunity();
+
UserResource user = ApiUtil.findUserByUsernameId(testRealm(), "test-user@localhost");
UserRepresentation userRep = user.toRepresentation();
userRep.setRequiredActions(Arrays.asList(UserModel.RequiredAction.UPDATE_PASSWORD.toString()));
@@ -168,6 +172,8 @@ public class LoginPageTest extends AbstractI18NTest {
// KEYCLOAK-3887
@Test
public void languageChangeConsentScreen() {
+ ProfileAssume.assumeCommunity();
+
// Set client, which requires consent
oauth.clientId("third-party");
From 5b179420fdcb669c9272344d45c96a69d8a6ed88 Mon Sep 17 00:00:00 2001
From: John Ament
Date: Tue, 22 Aug 2017 00:57:49 -0400
Subject: [PATCH 11/26] KEYCLOAK-5274: Check that authenticator config id is
null before attempting to fetch it. (#4404)
---
.../admin/AuthenticationManagementResource.java | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index 61f6254710..9503e02ea5 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -509,10 +509,13 @@ public class AuthenticationManagementResource {
rep.setId(execution.getId());
if (factory.isConfigurable()) {
- AuthenticatorConfigModel authenticatorConfig = realm.getAuthenticatorConfigById(execution.getAuthenticatorConfig());
+ String authenticatorConfigId = execution.getAuthenticatorConfig();
+ if(authenticatorConfigId != null) {
+ AuthenticatorConfigModel authenticatorConfig = realm.getAuthenticatorConfigById(authenticatorConfigId);
- if (authenticatorConfig != null) {
- rep.setAlias(authenticatorConfig.getAlias());
+ if (authenticatorConfig != null) {
+ rep.setAlias(authenticatorConfig.getAlias());
+ }
}
}
From b5ed8961f7239e1bce5f614fc4bae2ff0126ad54 Mon Sep 17 00:00:00 2001
From: Stian Thorgersen
Date: Tue, 22 Aug 2017 08:07:04 +0200
Subject: [PATCH 12/26] Add title attribute for iframe to suppress
accessibility errors (#4407)
---
adapters/oidc/js/src/main/resources/keycloak.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index a784936c78..04d76e5718 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -843,6 +843,7 @@
}
iframe.setAttribute('src', src );
+ iframe.setAttribute('title', 'keycloak-session-iframe' );
iframe.style.display = 'none';
document.body.appendChild(iframe);
From 20ac70d3fd095ece28a8a4bc2e7bf6009f76af28 Mon Sep 17 00:00:00 2001
From: Stian Thorgersen
Date: Tue, 22 Aug 2017 08:07:36 +0200
Subject: [PATCH 13/26] KEYCLOAK-5119 (#4400)
---
.../examples/rest/HelloResourceProvider.java | 3 +-
.../keycloak/protocol/saml/SamlService.java | 4 +-
.../services/resources/AccountService.java | 37 +++++++------------
.../java/org/keycloak/utils/MediaType.java | 4 ++
.../rest/TestApplicationResourceProvider.java | 15 ++++----
.../rest/resource/TestCacheResource.java | 5 +--
.../resources/TestApplicationResource.java | 6 +--
.../resources/TestingCacheResource.java | 12 +++---
.../client/resources/TestingResource.java | 9 ++---
9 files changed, 40 insertions(+), 55 deletions(-)
diff --git a/examples/providers/rest/src/main/java/org/keycloak/examples/rest/HelloResourceProvider.java b/examples/providers/rest/src/main/java/org/keycloak/examples/rest/HelloResourceProvider.java
index aebd677221..ebd8d1c991 100644
--- a/examples/providers/rest/src/main/java/org/keycloak/examples/rest/HelloResourceProvider.java
+++ b/examples/providers/rest/src/main/java/org/keycloak/examples/rest/HelloResourceProvider.java
@@ -22,7 +22,6 @@ import org.keycloak.services.resource.RealmResourceProvider;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
/**
* @author Stian Thorgersen
@@ -41,7 +40,7 @@ public class HelloResourceProvider implements RealmResourceProvider {
}
@GET
- @Produces(MediaType.TEXT_PLAIN)
+ @Produces("text/plain; charset=utf-8")
public String get() {
String name = session.getContext().getRealm().getDisplayName();
if (name == null) {
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 589dde3e6b..d63c98c144 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -58,6 +58,7 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.util.CacheControlUtil;
+import org.keycloak.utils.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
@@ -67,7 +68,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
@@ -594,7 +594,7 @@ public class SamlService extends AuthorizationEndpointBase {
@GET
@Path("clients/{client}")
- @Produces(MediaType.TEXT_HTML)
+ @Produces(MediaType.TEXT_HTML_UTF_8)
public Response idpInitiatedSSO(@PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) {
event.event(EventType.LOGIN);
CacheControlUtil.noBackButtonCacheControlHeader();
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index ac9bf807f6..b814abdb9c 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -59,9 +59,9 @@ import org.keycloak.services.validation.Validation;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.keycloak.storage.ReadOnlyException;
import org.keycloak.util.JsonSerialization;
+import org.keycloak.utils.MediaType;
import javax.ws.rs.*;
-import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
@@ -252,33 +252,24 @@ public class AccountService extends AbstractSecuredLocalService {
*/
@Path("/")
@GET
- @Produces(MediaType.TEXT_HTML)
public Response accountPage() {
- return forwardToPage(null, AccountPages.ACCOUNT);
- }
+ if (session.getContext().getRequestHeaders().getAcceptableMediaTypes().contains(MediaType.APPLICATION_JSON_TYPE)) {
+ requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
- /**
- * Get account information.
- *
- * @return
- */
- @Path("/")
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response accountPageJson() {
- requireOneOf(AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
-
- UserRepresentation rep = ModelToRepresentation.toRepresentation(session, realm, auth.getUser());
- if (rep.getAttributes() != null) {
- Iterator itr = rep.getAttributes().keySet().iterator();
- while (itr.hasNext()) {
- if (itr.next().startsWith("keycloak.")) {
- itr.remove();
+ UserRepresentation rep = ModelToRepresentation.toRepresentation(session, realm, auth.getUser());
+ if (rep.getAttributes() != null) {
+ Iterator itr = rep.getAttributes().keySet().iterator();
+ while (itr.hasNext()) {
+ if (itr.next().startsWith("keycloak.")) {
+ itr.remove();
+ }
}
}
- }
- return Cors.add(request, Response.ok(rep)).auth().allowedOrigins(auth.getToken()).build();
+ return Cors.add(request, Response.ok(rep).type(MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(auth.getToken()).build();
+ } else {
+ return forwardToPage(null, AccountPages.ACCOUNT);
+ }
}
public static UriBuilder totpUrl(UriBuilder base) {
diff --git a/services/src/main/java/org/keycloak/utils/MediaType.java b/services/src/main/java/org/keycloak/utils/MediaType.java
index acb0b4134e..4842f384f3 100644
--- a/services/src/main/java/org/keycloak/utils/MediaType.java
+++ b/services/src/main/java/org/keycloak/utils/MediaType.java
@@ -40,4 +40,8 @@ public class MediaType {
public static final String APPLICATION_JWT = "application/jwt";
public static final javax.ws.rs.core.MediaType APPLICATION_JWT_TYPE = new javax.ws.rs.core.MediaType("application", "jwt");
+ public static final String APPLICATION_XML = javax.ws.rs.core.MediaType.APPLICATION_XML;
+
+ public static final String TEXT_XML = javax.ws.rs.core.MediaType.TEXT_XML;
+
}
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java
index f47061a305..988108809d 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java
@@ -17,7 +17,6 @@
package org.keycloak.testsuite.rest;
-import org.jboss.resteasy.annotations.Query;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -30,6 +29,7 @@ import org.keycloak.representations.adapters.action.TestAvailabilityAction;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
+import org.keycloak.utils.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -38,7 +38,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
@@ -69,21 +68,21 @@ public class TestApplicationResourceProvider implements RealmResourceProvider {
}
@POST
- @Consumes(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN_UTF_8)
@Path("/admin/k_logout")
public void adminLogout(String data) throws JWSInputException {
adminLogoutActions.add(new JWSInput(data).readJsonContent(LogoutAction.class));
}
@POST
- @Consumes(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN_UTF_8)
@Path("/admin/k_push_not_before")
public void adminPushNotBefore(String data) throws JWSInputException {
adminPushNotBeforeActions.add(new JWSInput(data).readJsonContent(PushNotBeforeAction.class));
}
@POST
- @Consumes(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN_UTF_8)
@Path("/admin/k_test_available")
public void testAvailable(String data) throws JWSInputException {
adminTestAvailabilityAction.add(new JWSInput(data).readJsonContent(TestAvailabilityAction.class));
@@ -119,7 +118,7 @@ public class TestApplicationResourceProvider implements RealmResourceProvider {
}
@POST
- @Produces(MediaType.TEXT_HTML)
+ @Produces(MediaType.TEXT_HTML_UTF_8)
@Path("/{action}")
public String post(@PathParam("action") String action) {
String title = "APP_REQUEST";
@@ -148,7 +147,7 @@ public class TestApplicationResourceProvider implements RealmResourceProvider {
}
@GET
- @Produces(MediaType.TEXT_HTML)
+ @Produces(MediaType.TEXT_HTML_UTF_8)
@Path("/{action}")
public String get(@PathParam("action") String action) {
//String requestUri = session.getContext().getUri().getRequestUri().toString();
@@ -171,7 +170,7 @@ public class TestApplicationResourceProvider implements RealmResourceProvider {
@GET
@NoCache
- @Produces(MediaType.TEXT_HTML)
+ @Produces(MediaType.TEXT_HTML_UTF_8)
@Path("/get-account-profile")
public String getAccountProfile(@QueryParam("token") String token, @QueryParam("account-uri") String accountUri) {
StringBuilder sb = new StringBuilder();
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java
index 9847b27dcb..964e80da8b 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestCacheResource.java
@@ -27,18 +27,17 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
import org.infinispan.Cache;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.remoting.transport.Transport;
-import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.jgroups.JChannel;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
import org.keycloak.models.sessions.infinispan.util.InfinispanUtil;
import org.keycloak.testsuite.rest.representation.JGroupsStats;
+import org.keycloak.utils.MediaType;
/**
* @author Marek Posolda
@@ -82,7 +81,7 @@ public class TestCacheResource {
@GET
@Path("/clear")
- @Consumes(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN_UTF_8)
public void clear() {
cache.clear();
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java
index afefde3833..96c3c8df19 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java
@@ -17,18 +17,16 @@
package org.keycloak.testsuite.client.resources;
-import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.representations.adapters.action.LogoutAction;
import org.keycloak.representations.adapters.action.PushNotBeforeAction;
import org.keycloak.representations.adapters.action.TestAvailabilityAction;
+import org.keycloak.utils.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
/**
* @author Stian Thorgersen
@@ -56,7 +54,7 @@ public interface TestApplicationResource {
void clearAdminActions();
@GET
- @Produces(MediaType.TEXT_HTML)
+ @Produces(MediaType.TEXT_HTML_UTF_8)
@Path("/get-account-profile")
String getAccountProfile(@QueryParam("token") String token, @QueryParam("account-uri") String accountUri);
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingCacheResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingCacheResource.java
index e1aee2a374..1c362ea3a1 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingCacheResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingCacheResource.java
@@ -17,18 +17,16 @@
package org.keycloak.testsuite.client.resources;
-import java.util.Map;
-import java.util.Set;
+import org.keycloak.testsuite.rest.representation.JGroupsStats;
+import org.keycloak.testsuite.rest.representation.RemoteCacheStats;
+import org.keycloak.utils.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import org.keycloak.testsuite.rest.representation.JGroupsStats;
-import org.keycloak.testsuite.rest.representation.RemoteCacheStats;
+import java.util.Set;
/**
* @author Marek Posolda
@@ -55,7 +53,7 @@ public interface TestingCacheResource {
@GET
@Path("/clear")
- @Consumes(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN_UTF_8)
void clear();
@GET
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
index 2787c0e82f..080afcf769 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
@@ -18,14 +18,13 @@
package org.keycloak.testsuite.client.resources;
import org.jboss.resteasy.annotations.cache.NoCache;
-import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.components.TestProvider;
import org.keycloak.testsuite.rest.representation.AuthenticatorState;
-import org.keycloak.testsuite.rest.resource.TestCacheResource;
+import org.keycloak.utils.MediaType;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@@ -35,8 +34,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Map;
@@ -259,8 +256,8 @@ public interface TestingResource {
@POST
@Path("/run-on-server")
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces(MediaType.TEXT_PLAIN)
+ @Consumes(MediaType.TEXT_PLAIN_UTF_8)
+ @Produces(MediaType.TEXT_PLAIN_UTF_8)
String runOnServer(String runOnServer);
}
From ef32585f57f167fff33cab614cdae8f373f78cd5 Mon Sep 17 00:00:00 2001
From: Markus Heberling
Date: Tue, 22 Aug 2017 08:10:09 +0200
Subject: [PATCH 14/26] create JS source maps (#4365)
updated minify plugin to 1.7.6
switch minify plugin to use CLOSURE compiler
enable source map generation https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
include source maps in distribution files
---
adapters/oidc/js/pom.xml | 5 +++++
adapters/oidc/js/src/main/resources/keycloak.js | 2 +-
distribution/adapters/js-adapter-zip/assembly.xml | 1 +
distribution/adapters/js-adapter-zip/pom.xml | 2 +-
pom.xml | 2 +-
5 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/adapters/oidc/js/pom.xml b/adapters/oidc/js/pom.xml
index 8b4cc6789c..f1b83c17ad 100755
--- a/adapters/oidc/js/pom.xml
+++ b/adapters/oidc/js/pom.xml
@@ -38,6 +38,11 @@
com.samaxes.mavenminify-maven-plugin
+
+ CLOSURE
+ ECMASCRIPT5
+ true
+ min-js
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index 04d76e5718..ab6f78826a 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -221,7 +221,7 @@
var callbackState = {
state: state,
nonce: nonce,
- redirectUri: encodeURIComponent(redirectUri),
+ redirectUri: encodeURIComponent(redirectUri)
}
if (options && options.prompt) {
diff --git a/distribution/adapters/js-adapter-zip/assembly.xml b/distribution/adapters/js-adapter-zip/assembly.xml
index 14e0cc00b6..8111f783ea 100755
--- a/distribution/adapters/js-adapter-zip/assembly.xml
+++ b/distribution/adapters/js-adapter-zip/assembly.xml
@@ -30,6 +30,7 @@
**/*.js
+ **/*.map**/*.d.ts**/*.html
diff --git a/distribution/adapters/js-adapter-zip/pom.xml b/distribution/adapters/js-adapter-zip/pom.xml
index be37dc8729..8dcee562ae 100755
--- a/distribution/adapters/js-adapter-zip/pom.xml
+++ b/distribution/adapters/js-adapter-zip/pom.xml
@@ -50,7 +50,7 @@
org.keycloakkeycloak-js-adapter${project.build.directory}/unpacked/js-adapter
- *.js,*.d.ts
+ *.js,*.map,*.d.ts**/welcome-content/*
diff --git a/pom.xml b/pom.xml
index d4d990411e..7389fa745f 100755
--- a/pom.xml
+++ b/pom.xml
@@ -120,7 +120,7 @@
7.5.Final1.9.01.0.4
- 1.7.2
+ 1.7.62.3.71.1.0.Final1.6.5
From d3e559453b7dcf6f0d9f32c5a9a7f8c49403bb3a Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Wed, 16 Aug 2017 16:26:50 -0300
Subject: [PATCH 15/26] [KEYCLOAK-5015] - Updating Elytron Adapters
---
.../adapters/elytron/ElytronHttpFacade.java | 16 +++++++++++++++-
.../adapters/elytron/KeycloakSecurityRealm.java | 5 +++--
.../saml/elytron/KeycloakSecurityRealm.java | 5 +++--
.../shared-cli/adapter-elytron-install.cli | 4 ++--
.../cli/adapter-elytron-install-offline.cli | 4 ++--
.../shared-cli/adapter-elytron-install-saml.cli | 4 ++--
pom.xml | 4 ++--
testsuite/integration-arquillian/pom.xml | 2 +-
8 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java
index 4472af75f9..4941275f1e 100644
--- a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/ElytronHttpFacade.java
@@ -50,7 +50,9 @@ import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URLDecoder;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
/**
@@ -66,6 +68,7 @@ class ElytronHttpFacade implements OIDCHttpFacade {
private ElytronAccount account;
private SecurityIdentity securityIdentity;
private boolean restored;
+ private final Map headers = new HashMap<>();
public ElytronHttpFacade(HttpServerRequest request, AdapterDeploymentContext deploymentContext, CallbackHandler handler) {
this.request = request;
@@ -261,6 +264,7 @@ class ElytronHttpFacade implements OIDCHttpFacade {
@Override
public Response getResponse() {
return new Response() {
+
@Override
public void setStatus(final int status) {
responseConsumer = responseConsumer.andThen(response -> response.setStatusCode(status));
@@ -268,7 +272,17 @@ class ElytronHttpFacade implements OIDCHttpFacade {
@Override
public void addHeader(final String name, final String value) {
- responseConsumer = responseConsumer.andThen(response -> response.addResponseHeader(name, value));
+ headers.put(name, value);
+ responseConsumer = responseConsumer.andThen(new Consumer() {
+ @Override
+ public void accept(HttpServerResponse response) {
+ String latestValue = headers.get(name);
+
+ if (latestValue.equals(value)) {
+ response.addResponseHeader(name, latestValue);
+ }
+ }
+ });
}
@Override
diff --git a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java
index 6042ec82d1..eef2b26942 100644
--- a/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java
+++ b/adapters/oidc/wildfly-elytron/src/main/java/org/keycloak/adapters/elytron/KeycloakSecurityRealm.java
@@ -17,6 +17,7 @@
package org.keycloak.adapters.elytron;
import java.security.Principal;
+import java.security.spec.AlgorithmParameterSpec;
import java.util.Set;
import org.keycloak.KeycloakPrincipal;
@@ -54,7 +55,7 @@ public class KeycloakSecurityRealm implements SecurityRealm {
}
@Override
- public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
return SupportLevel.UNSUPPORTED;
}
@@ -92,7 +93,7 @@ public class KeycloakSecurityRealm implements SecurityRealm {
}
@Override
- public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
return SupportLevel.UNSUPPORTED;
}
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java
index 3207835360..f79b60d25e 100644
--- a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakSecurityRealm.java
@@ -17,6 +17,7 @@
package org.keycloak.adapters.saml.elytron;
import java.security.Principal;
+import java.security.spec.AlgorithmParameterSpec;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -53,7 +54,7 @@ public class KeycloakSecurityRealm implements SecurityRealm {
}
@Override
- public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> aClass, String s, AlgorithmParameterSpec algorithmParameterSpec) throws RealmUnavailableException {
return SupportLevel.UNSUPPORTED;
}
@@ -90,7 +91,7 @@ public class KeycloakSecurityRealm implements SecurityRealm {
}
@Override
- public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName) throws RealmUnavailableException {
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
return SupportLevel.UNSUPPORTED;
}
diff --git a/distribution/adapters/shared-cli/adapter-elytron-install.cli b/distribution/adapters/shared-cli/adapter-elytron-install.cli
index 16f17ce9a8..6ef26d01e5 100644
--- a/distribution/adapters/shared-cli/adapter-elytron-install.cli
+++ b/distribution/adapters/shared-cli/adapter-elytron-install.cli
@@ -36,10 +36,10 @@ else
end-if
if (outcome != success) of /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:read-resource
- /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-factories=[keycloak-oidc-http-server-mechanism-factory, global])
+ /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-mechanism-factories=[keycloak-oidc-http-server-mechanism-factory, global])
else
echo Keycloak HTTP Mechanism Factory already installed. Trying to install Keycloak OpenID Connect HTTP Mechanism Factory.
- /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-factories, value=keycloak-oidc-http-server-mechanism-factory)
+ /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-mechanism-factories, value=keycloak-oidc-http-server-mechanism-factory)
end-if
diff --git a/distribution/adapters/wildfly-adapter/cli/adapter-elytron-install-offline.cli b/distribution/adapters/wildfly-adapter/cli/adapter-elytron-install-offline.cli
index 8e0335ac02..76ec08cb17 100644
--- a/distribution/adapters/wildfly-adapter/cli/adapter-elytron-install-offline.cli
+++ b/distribution/adapters/wildfly-adapter/cli/adapter-elytron-install-offline.cli
@@ -38,10 +38,10 @@ else
end-if
if (outcome != success) of /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:read-resource
- /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-factories=[keycloak-oidc-http-server-mechanism-factory, global])
+ /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-mechanism-factories=[keycloak-oidc-http-server-mechanism-factory, global])
else
echo Keycloak HTTP Mechanism Factory already installed. Trying to install Keycloak OpenID Connect HTTP Mechanism Factory.
- /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-factories, value=keycloak-oidc-http-server-mechanism-factory)
+ /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-mechanism-factories, value=keycloak-oidc-http-server-mechanism-factory)
end-if
diff --git a/distribution/saml-adapters/shared-cli/adapter-elytron-install-saml.cli b/distribution/saml-adapters/shared-cli/adapter-elytron-install-saml.cli
index 1f24085459..a76109b809 100755
--- a/distribution/saml-adapters/shared-cli/adapter-elytron-install-saml.cli
+++ b/distribution/saml-adapters/shared-cli/adapter-elytron-install-saml.cli
@@ -36,10 +36,10 @@ else
end-if
if (outcome != success) of /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:read-resource
- /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-factories=[keycloak-saml-http-server-mechanism-factory, global])
+ /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:add(http-server-mechanism-factories=[keycloak-saml-http-server-mechanism-factory, global])
else
echo Keycloak HTTP Mechanism Factory already installed. Trying to install Keycloak SAML HTTP Mechanism Factory.
- /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-factories, value=keycloak-saml-http-server-mechanism-factory)
+ /subsystem=elytron/aggregate-http-server-mechanism-factory=keycloak-http-server-mechanism-factory:list-add(name=http-server-mechanism-factories, value=keycloak-saml-http-server-mechanism-factory)
end-if
if (outcome != success) of /subsystem=elytron/http-authentication-factory=keycloak-http-authentication:read-resource
diff --git a/pom.xml b/pom.xml
index 7389fa745f..0c5a771617 100755
--- a/pom.xml
+++ b/pom.xml
@@ -49,8 +49,8 @@
1.2.2.Final3.0.0.Beta30
- 1.1.0.Beta32
- 1.0.0.Beta14
+ 1.1.0.CR4
+ 1.0.0.CR10.66.154.5
diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index 0bcb2b899b..cb25e181fa 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -45,7 +45,7 @@
2.53.02.0.1.Final2.1.0.Alpha3
- 2.1.0.Alpha2
+ 2.1.0.Beta11.0.1.Final1.2.0.Beta22.2.2
From a6dfb4ccdd607fc37a7a2f04537f43d348d8616a Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Thu, 17 Aug 2017 12:32:19 -0300
Subject: [PATCH 16/26] [KEYCLOAK-5015] - Support for Elytron capabilities in
subsystem
---
.../oidc/wildfly/wildfly-subsystem/pom.xml | 8 +
...stractAdapterConfigurationAddHandler.java} | 29 +-
...bstractAdapterConfigurationDefinition.java | 164 +++++++++++
...actAdapterConfigurationRemoveHandler.java} | 6 +-
...erConfigurationWriteAttributeHandler.java} | 10 +-
...cloakAdapterConfigDeploymentProcessor.java | 34 +++
.../KeycloakAdapterConfigService.java | 54 +++-
.../KeycloakDependencyProcessorWildFly.java | 3 +-
.../adapter/extension/KeycloakExtension.java | 7 +-
...cloakHttpAuthenticationFactoryService.java | 67 +++++
...henticationMechanismFactoryDefinition.java | 117 ++++++++
.../extension/KeycloakSubsystemParser.java | 42 ++-
.../extension/SecureDeploymentDefinition.java | 184 +++++--------
.../extension/SecureServerDefinition.java | 258 ++++++++++++++++++
.../extension/LocalDescriptions.properties | 43 +++
.../resources/schema/wildfly-keycloak_1_1.xsd | 9 +-
.../extension/SubsystemParsingTestCase.java | 2 +-
.../adapter/extension/keycloak-1.1.xml | 16 ++
.../main/module.xml | 4 +
testsuite/integration-arquillian/pom.xml | 4 +-
20 files changed, 885 insertions(+), 176 deletions(-)
rename adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/{SecureDeploymentAddHandler.java => AbstractAdapterConfigurationAddHandler.java} (58%)
create mode 100755 adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationDefinition.java
rename adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/{SecureDeploymentRemoveHandler.java => AbstractAdapterConfigurationRemoveHandler.java} (85%)
rename adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/{SecureDeploymentWriteAttributeHandler.java => AbstractAdapterConfigurationWriteAttributeHandler.java} (83%)
create mode 100644 adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpAuthenticationFactoryService.java
create mode 100644 adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpServerAuthenticationMechanismFactoryDefinition.java
create mode 100755 adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureServerDefinition.java
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/pom.xml b/adapters/oidc/wildfly/wildfly-subsystem/pom.xml
index 1d8e6cf916..8c18a39a74 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/pom.xml
+++ b/adapters/oidc/wildfly/wildfly-subsystem/pom.xml
@@ -68,6 +68,10 @@
wildfly-web-commonprovided
+
+ org.wildfly.security
+ wildfly-elytron
+ org.jboss.loggingjboss-logging-annotations
@@ -101,5 +105,9 @@
keycloak-wildfly-adapter${project.version}
+
+ org.keycloak
+ keycloak-wildfly-elytron-oidc-adapter
+
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentAddHandler.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationAddHandler.java
similarity index 58%
rename from adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentAddHandler.java
rename to adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationAddHandler.java
index 110d385a75..55c83ca96b 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentAddHandler.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationAddHandler.java
@@ -17,41 +17,32 @@
package org.keycloak.subsystem.adapter.extension;
+import java.util.List;
+
import org.jboss.as.controller.AbstractAddStepHandler;
-import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.dmr.ModelNode;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
-import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
-
/**
* Add a deployment to a realm.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
*/
-public final class SecureDeploymentAddHandler extends AbstractAddStepHandler {
+abstract class AbstractAdapterConfigurationAddHandler extends AbstractAddStepHandler {
- public static SecureDeploymentAddHandler INSTANCE = new SecureDeploymentAddHandler();
+ private final boolean elytronEnabled;
- private SecureDeploymentAddHandler() {}
-
- @Override
- protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
- // TODO: localize exception. get id number
- if (!operation.get(OP).asString().equals(ADD)) {
- throw new OperationFailedException("Unexpected operation for add secure deployment. operation=" + operation.toString());
- }
-
- for (AttributeDefinition attr : SecureDeploymentDefinition.ALL_ATTRIBUTES) {
- attr.validateAndSet(operation, model);
- }
+ AbstractAdapterConfigurationAddHandler(RuntimeCapability runtimeCapability, List attributes) {
+ super(runtimeCapability, attributes);
+ elytronEnabled = runtimeCapability != null;
}
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
KeycloakAdapterConfigService ckService = KeycloakAdapterConfigService.getInstance();
- ckService.addSecureDeployment(operation, context.resolveExpressions(model));
+ ckService.addSecureDeployment(operation, context.resolveExpressions(model), elytronEnabled);
}
}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationDefinition.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationDefinition.java
new file mode 100755
index 0000000000..613c946f4f
--- /dev/null
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationDefinition.java
@@ -0,0 +1,164 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.subsystem.adapter.extension;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.operations.validation.IntRangeValidator;
+import org.jboss.as.controller.operations.validation.StringLengthValidator;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Defines attributes and operations for a secure-deployment.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+abstract class AbstractAdapterConfigurationDefinition extends SimpleResourceDefinition {
+
+ protected static final SimpleAttributeDefinition REALM =
+ new SimpleAttributeDefinitionBuilder("realm", ModelType.STRING, true)
+ .setXmlName("realm")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+ protected static final SimpleAttributeDefinition RESOURCE =
+ new SimpleAttributeDefinitionBuilder("resource", ModelType.STRING, true)
+ .setXmlName("resource")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+ protected static final SimpleAttributeDefinition USE_RESOURCE_ROLE_MAPPINGS =
+ new SimpleAttributeDefinitionBuilder("use-resource-role-mappings", ModelType.BOOLEAN, true)
+ .setXmlName("use-resource-role-mappings")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition BEARER_ONLY =
+ new SimpleAttributeDefinitionBuilder("bearer-only", ModelType.BOOLEAN, true)
+ .setXmlName("bearer-only")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition ENABLE_BASIC_AUTH =
+ new SimpleAttributeDefinitionBuilder("enable-basic-auth", ModelType.BOOLEAN, true)
+ .setXmlName("enable-basic-auth")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition PUBLIC_CLIENT =
+ new SimpleAttributeDefinitionBuilder("public-client", ModelType.BOOLEAN, true)
+ .setXmlName("public-client")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition TURN_OFF_CHANGE_SESSION =
+ new SimpleAttributeDefinitionBuilder("turn-off-change-session-id-on-login", ModelType.BOOLEAN, true)
+ .setXmlName("turn-off-change-session-id-on-login")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition TOKEN_MINIMUM_TIME_TO_LIVE =
+ new SimpleAttributeDefinitionBuilder("token-minimum-time-to-live", ModelType.INT, true)
+ .setXmlName("token-minimum-time-to-live")
+ .setValidator(new IntRangeValidator(-1, true))
+ .setAllowExpression(true)
+ .build();
+ protected static final SimpleAttributeDefinition MIN_TIME_BETWEEN_JWKS_REQUESTS =
+ new SimpleAttributeDefinitionBuilder("min-time-between-jwks-requests", ModelType.INT, true)
+ .setXmlName("min-time-between-jwks-requests")
+ .setValidator(new IntRangeValidator(-1, true))
+ .setAllowExpression(true)
+ .build();
+
+ static final List DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList();
+
+ static {
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(REALM);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(ENABLE_BASIC_AUTH);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_CLIENT);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(TURN_OFF_CHANGE_SESSION);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(TOKEN_MINIMUM_TIME_TO_LIVE);
+ DEPLOYMENT_ONLY_ATTRIBUTES.add(MIN_TIME_BETWEEN_JWKS_REQUESTS);
+ }
+
+ static final List ALL_ATTRIBUTES = new ArrayList();
+
+ static {
+ ALL_ATTRIBUTES.addAll(DEPLOYMENT_ONLY_ATTRIBUTES);
+ ALL_ATTRIBUTES.addAll(SharedAttributeDefinitons.ATTRIBUTES);
+ }
+
+ static final Map XML_ATTRIBUTES = new HashMap();
+
+ static {
+ for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
+ XML_ATTRIBUTES.put(def.getXmlName(), def);
+ }
+ }
+
+ private static final Map DEFINITION_LOOKUP = new HashMap();
+ static {
+ for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
+ DEFINITION_LOOKUP.put(def.getXmlName(), def);
+ }
+ }
+
+ private final AbstractAdapterConfigurationWriteAttributeHandler attrWriteHandler;
+ private final List attributes;
+
+ protected AbstractAdapterConfigurationDefinition(String name, List attributes, AbstractAdapterConfigurationAddHandler addHandler, AbstractAdapterConfigurationRemoveHandler removeHandler, AbstractAdapterConfigurationWriteAttributeHandler attrWriteHandler) {
+ super(PathElement.pathElement(name),
+ KeycloakExtension.getResourceDescriptionResolver(name),
+ addHandler,
+ removeHandler);
+ this.attributes = attributes;
+ this.attrWriteHandler = attrWriteHandler;
+ }
+
+ @Override
+ public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+ super.registerOperations(resourceRegistration);
+ resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+ }
+
+ @Override
+ public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+ super.registerAttributes(resourceRegistration);
+ for (AttributeDefinition attrDef : this.attributes) {
+ resourceRegistration.registerReadWriteAttribute(attrDef, null, this.attrWriteHandler);
+ }
+ }
+
+ public static SimpleAttributeDefinition lookup(String name) {
+ return DEFINITION_LOOKUP.get(name);
+ }
+}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentRemoveHandler.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationRemoveHandler.java
similarity index 85%
rename from adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentRemoveHandler.java
rename to adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationRemoveHandler.java
index 7088ec0cf9..2066aed3f4 100644
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentRemoveHandler.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationRemoveHandler.java
@@ -27,11 +27,7 @@ import org.jboss.dmr.ModelNode;
*
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
*/
-public final class SecureDeploymentRemoveHandler extends AbstractRemoveStepHandler {
-
- public static SecureDeploymentRemoveHandler INSTANCE = new SecureDeploymentRemoveHandler();
-
- private SecureDeploymentRemoveHandler() {}
+abstract class AbstractAdapterConfigurationRemoveHandler extends AbstractRemoveStepHandler {
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentWriteAttributeHandler.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationWriteAttributeHandler.java
similarity index 83%
rename from adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentWriteAttributeHandler.java
rename to adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationWriteAttributeHandler.java
index 908526c828..127ea538f1 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureDeploymentWriteAttributeHandler.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/AbstractAdapterConfigurationWriteAttributeHandler.java
@@ -31,14 +31,10 @@ import java.util.List;
*
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
*/
-public class SecureDeploymentWriteAttributeHandler extends AbstractWriteAttributeHandler {
+abstract class AbstractAdapterConfigurationWriteAttributeHandler extends AbstractWriteAttributeHandler {
- public SecureDeploymentWriteAttributeHandler(List definitions) {
- this(definitions.toArray(new AttributeDefinition[definitions.size()]));
- }
-
- public SecureDeploymentWriteAttributeHandler(AttributeDefinition... definitions) {
- super(definitions);
+ AbstractAdapterConfigurationWriteAttributeHandler(List definitions) {
+ super(definitions.toArray(new AttributeDefinition[definitions.size()]));
}
@Override
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigDeploymentProcessor.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigDeploymentProcessor.java
index 24e9ac0b74..1500808e32 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigDeploymentProcessor.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigDeploymentProcessor.java
@@ -25,7 +25,9 @@ import org.jboss.as.web.common.WarMetaData;
import org.jboss.logging.Logger;
import org.jboss.metadata.javaee.spec.ParamValueMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.spec.ListenerMetaData;
import org.jboss.metadata.web.spec.LoginConfigMetaData;
+import org.keycloak.adapters.elytron.KeycloakConfigurationServletListener;
import org.keycloak.subsystem.adapter.logging.KeycloakLogger;
import java.util.ArrayList;
@@ -69,6 +71,9 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
if (service.isSecureDeployment(deploymentUnit) && service.isDeploymentConfigured(deploymentUnit)) {
addKeycloakAuthData(phaseContext, service);
+ } else if (service.isElytronEnabled(deploymentUnit)) {
+ WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+ addConfigurationListener(warMetaData);
}
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
@@ -99,6 +104,10 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
loginConfig.setAuthMethod("KEYCLOAK");
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
+
+ if (service.isElytronEnabled(deploymentUnit)) {
+ addConfigurationListener(warMetaData);
+ }
}
private void addJSONData(String json, WarMetaData warMetaData) {
@@ -121,6 +130,31 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
webMetaData.setContextParams(contextParams);
}
+ private void addConfigurationListener(WarMetaData warMetaData) {
+ if (warMetaData == null) {
+ return;
+ }
+
+ JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+ if (webMetaData == null) {
+ webMetaData = new JBossWebMetaData();
+ warMetaData.setMergedJBossWebMetaData(webMetaData);
+ }
+
+ LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+ if (loginConfig == null) {
+ return;
+ }
+ if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) {
+ return;
+ }
+ ListenerMetaData listenerMetaData = new ListenerMetaData();
+
+ listenerMetaData.setListenerClass(KeycloakConfigurationServletListener.class.getName());
+
+ webMetaData.getListeners().add(listenerMetaData);
+ }
+
@Override
public void undeploy(DeploymentUnit du) {
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java
index 5a71e615a8..496c311982 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java
@@ -23,8 +23,11 @@ import org.jboss.dmr.ModelNode;
import org.jboss.dmr.Property;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
@@ -50,6 +53,7 @@ public final class KeycloakAdapterConfigService {
// keycloak-secured deployments
private final Map secureDeployments = new HashMap();
+ private final Set elytronEnabledDeployments = new HashSet<>();
private KeycloakAdapterConfigService() {
@@ -68,9 +72,13 @@ public final class KeycloakAdapterConfigService {
this.realms.remove(realmNameFromOp(operation));
}
- public void addSecureDeployment(ModelNode operation, ModelNode model) {
+ public void addSecureDeployment(ModelNode operation, ModelNode model, boolean elytronEnabled) {
ModelNode deployment = model.clone();
- this.secureDeployments.put(deploymentNameFromOp(operation), deployment);
+ String name = deploymentNameFromOp(operation);
+ this.secureDeployments.put(name, deployment);
+ if (elytronEnabled) {
+ elytronEnabledDeployments.add(name);
+ }
}
public void updateSecureDeployment(ModelNode operation, String attrName, ModelNode resolvedValue) {
@@ -79,7 +87,9 @@ public final class KeycloakAdapterConfigService {
}
public void removeSecureDeployment(ModelNode operation) {
- this.secureDeployments.remove(deploymentNameFromOp(operation));
+ String name = deploymentNameFromOp(operation);
+ this.secureDeployments.remove(name);
+ elytronEnabledDeployments.remove(name);
}
public void addCredential(ModelNode operation, ModelNode model) {
@@ -187,7 +197,19 @@ public final class KeycloakAdapterConfigService {
}
private String deploymentNameFromOp(ModelNode operation) {
- return valueFromOpAddress(SecureDeploymentDefinition.TAG_NAME, operation);
+ String deploymentName = valueFromOpAddress(SecureDeploymentDefinition.TAG_NAME, operation);
+
+ if (deploymentName == null) {
+ deploymentName = valueFromOpAddress(KeycloakHttpServerAuthenticationMechanismFactoryDefinition.TAG_NAME, operation);
+ }
+
+ if (deploymentName == null) {
+ deploymentName = valueFromOpAddress(SecureServerDefinition.TAG_NAME, operation);
+ }
+
+ if (deploymentName == null) throw new RuntimeException("Can't find deployment name in address " + operation);
+
+ return deploymentName;
}
private String credentialNameFromOp(ModelNode operation) {
@@ -199,9 +221,7 @@ public final class KeycloakAdapterConfigService {
}
private String valueFromOpAddress(String addrElement, ModelNode operation) {
- String deploymentName = getValueOfAddrElement(operation.get(ADDRESS), addrElement);
- if (deploymentName == null) throw new RuntimeException("Can't find '" + addrElement + "' in address " + operation.toString());
- return deploymentName;
+ return getValueOfAddrElement(operation.get(ADDRESS), addrElement);
}
private String getValueOfAddrElement(ModelNode address, String elementName) {
@@ -241,8 +261,22 @@ public final class KeycloakAdapterConfigService {
return json.toJSONString(true);
}
+ public String getJSON(String deploymentName) {
+ ModelNode deployment = this.secureDeployments.get(deploymentName);
+ String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
+ ModelNode realm = this.realms.get(realmName);
+
+ ModelNode json = new ModelNode();
+ json.get(RealmDefinition.TAG_NAME).set(realmName);
+
+ // Realm values set first. Some can be overridden by deployment values.
+ if (realm != null) setJSONValues(json, realm);
+ setJSONValues(json, deployment);
+ return json.toJSONString(true);
+ }
+
private void setJSONValues(ModelNode json, ModelNode values) {
- for (Property prop : values.asPropertyList()) {
+ for (Property prop : new ArrayList<>(values.asPropertyList())) {
String name = prop.getName();
ModelNode value = prop.getValue();
if (value.isDefined()) {
@@ -258,6 +292,10 @@ public final class KeycloakAdapterConfigService {
return this.secureDeployments.containsKey(deploymentName);
}
+ public boolean isElytronEnabled(DeploymentUnit deploymentUnit) {
+ return elytronEnabledDeployments.contains(preferredDeploymentName(deploymentUnit));
+ }
+
private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
String deploymentName = preferredDeploymentName(deploymentUnit);
return this.secureDeployments.containsKey(deploymentName)
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessorWildFly.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessorWildFly.java
index e306a7f630..61d670c8cd 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessorWildFly.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessorWildFly.java
@@ -29,13 +29,14 @@ import org.jboss.modules.ModuleLoader;
*/
public class KeycloakDependencyProcessorWildFly extends KeycloakDependencyProcessor {
+ private static final ModuleIdentifier KEYCLOAK_ELYTRON_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-elytron-oidc-adapter");
private static final ModuleIdentifier KEYCLOAK_WILDFLY_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-wildfly-adapter");
private static final ModuleIdentifier KEYCLOAK_UNDERTOW_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-undertow-adapter");
@Override
protected void addPlatformSpecificModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
- // ModuleDependency(ModuleLoader moduleLoader, ModuleIdentifier identifier, boolean optional, boolean export, boolean importServices, boolean userSpecified)
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_WILDFLY_ADAPTER, false, false, true, false));
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_UNDERTOW_ADAPTER, false, false, false, false));
+ moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_ELYTRON_ADAPTER, true, false, false, false));
}
}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakExtension.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakExtension.java
index d04e72d403..52113c0825 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakExtension.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakExtension.java
@@ -47,8 +47,9 @@ public class KeycloakExtension implements Extension {
private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
static final RealmDefinition REALM_DEFINITION = new RealmDefinition();
static final SecureDeploymentDefinition SECURE_DEPLOYMENT_DEFINITION = new SecureDeploymentDefinition();
+ static final SecureServerDefinition SECURE_SERVER_DEFINITION = new SecureServerDefinition();
static final CredentialDefinition CREDENTIAL_DEFINITION = new CredentialDefinition();
- static final RedirecRewritetRuleDefinition REDIRECT_RULE_DEFINITON = new RedirecRewritetRuleDefinition();
+ static final RedirecRewritetRuleDefinition REDIRECT_RULE_DEFINITON = new RedirecRewritetRuleDefinition();
public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
@@ -80,6 +81,10 @@ public class KeycloakExtension implements Extension {
secureDeploymentRegistration.registerSubModel(CREDENTIAL_DEFINITION);
secureDeploymentRegistration.registerSubModel(REDIRECT_RULE_DEFINITON);
+ ManagementResourceRegistration secureServerRegistration = registration.registerSubModel(SECURE_SERVER_DEFINITION);
+ secureServerRegistration.registerSubModel(CREDENTIAL_DEFINITION);
+ secureServerRegistration.registerSubModel(REDIRECT_RULE_DEFINITON);
+
subsystem.registerXMLElementWriter(PARSER);
}
}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpAuthenticationFactoryService.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpAuthenticationFactoryService.java
new file mode 100644
index 0000000000..94fb8e566d
--- /dev/null
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpAuthenticationFactoryService.java
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.subsystem.adapter.extension;
+
+import org.jboss.msc.service.Service;
+import org.jboss.msc.service.StartContext;
+import org.jboss.msc.service.StartException;
+import org.jboss.msc.service.StopContext;
+import org.jboss.msc.value.InjectedValue;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.elytron.KeycloakHttpServerAuthenticationMechanismFactory;
+import org.wildfly.security.auth.server.SecurityDomain;
+import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
+import org.wildfly.security.http.util.SetMechanismInformationMechanismFactory;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * @author Pedro Igor
+ */
+public class KeycloakHttpAuthenticationFactoryService implements Service {
+
+ private final String factoryName;
+ private HttpServerAuthenticationMechanismFactory httpAuthenticationFactory;
+
+ public KeycloakHttpAuthenticationFactoryService(String factoryName) {
+ this.factoryName = factoryName;
+ }
+
+ @Override
+ public void start(StartContext context) throws StartException {
+ KeycloakAdapterConfigService adapterConfigService = KeycloakAdapterConfigService.getInstance();
+ String config = adapterConfigService.getJSON(this.factoryName);
+ this.httpAuthenticationFactory = new KeycloakHttpServerAuthenticationMechanismFactory(createDeploymentContext(config.getBytes()));
+ }
+
+ @Override
+ public void stop(StopContext context) {
+ this.httpAuthenticationFactory = null;
+ }
+
+ @Override
+ public HttpServerAuthenticationMechanismFactory getValue() throws IllegalStateException, IllegalArgumentException {
+ return new SetMechanismInformationMechanismFactory(this.httpAuthenticationFactory);
+ }
+
+ private AdapterDeploymentContext createDeploymentContext(byte[] config) {
+ return new AdapterDeploymentContext(KeycloakDeploymentBuilder.build(new ByteArrayInputStream(config)));
+ }
+}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpServerAuthenticationMechanismFactoryDefinition.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpServerAuthenticationMechanismFactoryDefinition.java
new file mode 100644
index 0000000000..1e177a49f4
--- /dev/null
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakHttpServerAuthenticationMechanismFactoryDefinition.java
@@ -0,0 +1,117 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.subsystem.adapter.extension;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
+import static org.keycloak.subsystem.adapter.extension.KeycloakHttpServerAuthenticationMechanismFactoryDefinition.KeycloakHttpServerAuthenticationMechanismFactoryAddHandler.HTTP_SERVER_AUTHENTICATION_CAPABILITY;
+
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.capability.RuntimeCapability;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.ServiceController;
+import org.jboss.msc.service.ServiceName;
+import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
+
+/**
+ * A {@link SimpleResourceDefinition} that can be used to configure a {@link org.keycloak.adapters.elytron.KeycloakHttpServerAuthenticationMechanismFactory}
+ * and expose it as a capability for other subsystems.
+ *
+ * @author Pedro Igor
+ */
+class KeycloakHttpServerAuthenticationMechanismFactoryDefinition extends AbstractAdapterConfigurationDefinition {
+
+ static final String TAG_NAME = "http-server-mechanism-factory";
+
+ KeycloakHttpServerAuthenticationMechanismFactoryDefinition() {
+ this(TAG_NAME);
+ }
+
+ KeycloakHttpServerAuthenticationMechanismFactoryDefinition(String tagName) {
+ super(tagName, ALL_ATTRIBUTES, new KeycloakHttpServerAuthenticationMechanismFactoryAddHandler(), new KeycloakHttpServerAuthenticationMechanismFactoryRemoveHandler(), new KeycloakHttpServerAuthenticationMechanismFactoryWriteHandler());
+ }
+
+ /**
+ * A {@link AbstractAdapterConfigurationAddHandler} that exposes a {@link KeycloakHttpServerAuthenticationMechanismFactoryDefinition}
+ * as a capability through the installation of a {@link KeycloakHttpAuthenticationFactoryService}.
+ *
+ * @author Pedro Igor
+ */
+ static final class KeycloakHttpServerAuthenticationMechanismFactoryAddHandler extends AbstractAdapterConfigurationAddHandler {
+
+ static final String HTTP_SERVER_AUTHENTICATION_CAPABILITY = "org.wildfly.security.http-server-mechanism-factory";
+ static final RuntimeCapability HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY = RuntimeCapability
+ .Builder.of(HTTP_SERVER_AUTHENTICATION_CAPABILITY, true, HttpServerAuthenticationMechanismFactory.class)
+ .build();
+
+ KeycloakHttpServerAuthenticationMechanismFactoryAddHandler() {
+ super(HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY, ALL_ATTRIBUTES);
+ }
+
+ @Override
+ protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.performRuntime(context, operation, model);
+ installCapability(context, operation);
+ }
+
+ static void installCapability(OperationContext context, ModelNode operation) {
+ PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
+ String factoryName = pathAddress.getLastElement().getValue();
+ ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
+ KeycloakHttpAuthenticationFactoryService service = new KeycloakHttpAuthenticationFactoryService(factoryName);
+ context.getServiceTarget().addService(serviceName, service).setInitialMode(ServiceController.Mode.ACTIVE).install();
+ }
+ }
+
+ /**
+ * A {@link AbstractAdapterConfigurationRemoveHandler} that handles the removal of {@link KeycloakHttpServerAuthenticationMechanismFactoryDefinition}.
+ *
+ * @author Pedro Igor
+ */
+ static final class KeycloakHttpServerAuthenticationMechanismFactoryRemoveHandler extends AbstractAdapterConfigurationRemoveHandler {
+ @Override
+ protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.performRuntime(context, operation, model);
+ PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
+ String factoryName = pathAddress.getLastElement().getValue();
+ ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
+
+ context.removeService(serviceName);
+ }
+
+ @Override
+ protected void recoverServices(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.recoverServices(context, operation, model);
+ KeycloakHttpServerAuthenticationMechanismFactoryAddHandler.installCapability(context, operation);
+ }
+ }
+
+ /**
+ * A {@link AbstractAdapterConfigurationWriteAttributeHandler} that updates attributes on a {@link KeycloakHttpServerAuthenticationMechanismFactoryDefinition}.
+ *
+ * @author Pedro Igor
+ */
+ static final class KeycloakHttpServerAuthenticationMechanismFactoryWriteHandler extends AbstractAdapterConfigurationWriteAttributeHandler {
+ KeycloakHttpServerAuthenticationMechanismFactoryWriteHandler() {
+ super(ALL_ATTRIBUTES);
+ }
+ }
+}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java
index 79555e3b7b..a8d50aeb3d 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java
@@ -62,6 +62,9 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader
resourcesToAdd) throws XMLStreamException {
+ readSecureResource(KeycloakExtension.SECURE_DEPLOYMENT_DEFINITION.TAG_NAME, KeycloakExtension.SECURE_DEPLOYMENT_DEFINITION, reader, resourcesToAdd);
+ }
+
+ private void readSecureServer(XMLExtendedStreamReader reader, List resourcesToAdd) throws XMLStreamException {
+ readSecureResource(KeycloakExtension.SECURE_SERVER_DEFINITION.TAG_NAME, KeycloakExtension.SECURE_SERVER_DEFINITION, reader, resourcesToAdd);
+ }
+
+ private void readSecureResource(String tagName, AbstractAdapterConfigurationDefinition resource, XMLExtendedStreamReader reader, List resourcesToAdd) throws XMLStreamException {
String name = readNameAttribute(reader);
ModelNode addSecureDeployment = new ModelNode();
addSecureDeployment.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
- PathElement.pathElement(SecureDeploymentDefinition.TAG_NAME, name));
+ PathElement.pathElement(tagName, name));
addSecureDeployment.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
List credentialsToAdd = new ArrayList();
List redirectRulesToAdd = new ArrayList();
while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
- String tagName = reader.getLocalName();
- if (tagName.equals(CredentialDefinition.TAG_NAME)) {
+ String localName = reader.getLocalName();
+ if (localName.equals(CredentialDefinition.TAG_NAME)) {
readCredential(reader, addr, credentialsToAdd);
continue;
}
- if (tagName.equals(RedirecRewritetRuleDefinition.TAG_NAME)) {
+ if (localName.equals(RedirecRewritetRuleDefinition.TAG_NAME)) {
readRewriteRule(reader, addr, redirectRulesToAdd);
continue;
}
- SimpleAttributeDefinition def = SecureDeploymentDefinition.lookup(tagName);
- if (def == null) throw new XMLStreamException("Unknown secure-deployment tag " + tagName);
+ SimpleAttributeDefinition def = resource.lookup(localName);
+ if (def == null) throw new XMLStreamException("Unknown secure-deployment tag " + localName);
def.parseAndSetParameter(reader.getElementText(), addSecureDeployment, reader);
}
@@ -236,6 +247,7 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader
attributes, XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
+ if (!context.getModelNode().get(tagName).isDefined()) {
return;
}
- for (Property deployment : context.getModelNode().get(SecureDeploymentDefinition.TAG_NAME).asPropertyList()) {
- writer.writeStartElement(SecureDeploymentDefinition.TAG_NAME);
+ for (Property deployment : context.getModelNode().get(tagName).asPropertyList()) {
+ writer.writeStartElement(tagName);
writer.writeAttribute("name", deployment.getName());
ModelNode deploymentElements = deployment.getValue();
- for (AttributeDefinition element : SecureDeploymentDefinition.ALL_ATTRIBUTES) {
+ for (AttributeDefinition element : attributes) {
element.marshallAsElement(deploymentElements, writer);
}
@@ -271,7 +291,7 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader
DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList();
- static {
- DEPLOYMENT_ONLY_ATTRIBUTES.add(REALM);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(ENABLE_BASIC_AUTH);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_CLIENT);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(TURN_OFF_CHANGE_SESSION);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(TOKEN_MINIMUM_TIME_TO_LIVE);
- DEPLOYMENT_ONLY_ATTRIBUTES.add(MIN_TIME_BETWEEN_JWKS_REQUESTS);
- }
-
- protected static final List ALL_ATTRIBUTES = new ArrayList();
- static {
- ALL_ATTRIBUTES.addAll(DEPLOYMENT_ONLY_ATTRIBUTES);
- ALL_ATTRIBUTES.addAll(SharedAttributeDefinitons.ATTRIBUTES);
- }
-
- private static final Map DEFINITION_LOOKUP = new HashMap();
- static {
- for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
- DEFINITION_LOOKUP.put(def.getXmlName(), def);
- }
- }
-
- private static SecureDeploymentWriteAttributeHandler attrHandler = new SecureDeploymentWriteAttributeHandler(ALL_ATTRIBUTES);
+ static final String TAG_NAME = "secure-deployment";
public SecureDeploymentDefinition() {
- super(PathElement.pathElement(TAG_NAME),
- KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
- SecureDeploymentAddHandler.INSTANCE,
- SecureDeploymentRemoveHandler.INSTANCE);
+ super(TAG_NAME, ALL_ATTRIBUTES, new SecureDeploymentAddHandler(), new SecureDeploymentRemoveHandler(), new SecureDeploymentWriteAttributeHandler());
}
- @Override
- public void registerOperations(ManagementResourceRegistration resourceRegistration) {
- super.registerOperations(resourceRegistration);
- resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
- }
+ /**
+ * Add a deployment to a realm.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+ static final class SecureDeploymentAddHandler extends AbstractAdapterConfigurationAddHandler {
- @Override
- public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
- super.registerAttributes(resourceRegistration);
- for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
- resourceRegistration.registerReadWriteAttribute(attrDef, null, attrHandler);
+ static final String HTTP_SERVER_AUTHENTICATION_CAPABILITY = "org.wildfly.security.http-server-mechanism-factory";
+ static RuntimeCapability HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY;
+
+ static {
+ try {
+ HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY = RuntimeCapability
+ .Builder.of(HTTP_SERVER_AUTHENTICATION_CAPABILITY, true, HttpServerAuthenticationMechanismFactory.class)
+ .build();
+ } catch (NoClassDefFoundError ncfe) {
+ // ignore, Elytron not present thus no capability will be published by this resource definition
+ }
+ }
+
+ SecureDeploymentAddHandler() {
+ super(HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY, ALL_ATTRIBUTES);
+ }
+
+ @Override
+ protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.performRuntime(context, operation, model);
+ if (HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY != null) {
+ installCapability(context, operation);
+ }
+ }
+
+ static void installCapability(OperationContext context, ModelNode operation) {
+ PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
+ String factoryName = pathAddress.getLastElement().getValue();
+ ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
+ KeycloakHttpAuthenticationFactoryService service = new KeycloakHttpAuthenticationFactoryService(factoryName);
+ ServiceTarget serviceTarget = context.getServiceTarget();
+ serviceTarget.addService(serviceName, service).setInitialMode(ServiceController.Mode.ACTIVE).install();
}
}
- public static SimpleAttributeDefinition lookup(String name) {
- return DEFINITION_LOOKUP.get(name);
+ /**
+ * Remove a secure-deployment from a realm.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+ static final class SecureDeploymentRemoveHandler extends AbstractAdapterConfigurationRemoveHandler {}
+
+ /**
+ * Update an attribute on a secure-deployment.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+ static final class SecureDeploymentWriteAttributeHandler extends AbstractAdapterConfigurationWriteAttributeHandler {
+ SecureDeploymentWriteAttributeHandler() {
+ super(ALL_ATTRIBUTES);
+ }
}
}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureServerDefinition.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureServerDefinition.java
new file mode 100755
index 0000000000..7d8fd05dfd
--- /dev/null
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SecureServerDefinition.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.subsystem.adapter.extension;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
+import static org.keycloak.subsystem.adapter.extension.KeycloakHttpServerAuthenticationMechanismFactoryDefinition.KeycloakHttpServerAuthenticationMechanismFactoryAddHandler.HTTP_SERVER_AUTHENTICATION_CAPABILITY;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import io.undertow.io.IoCallback;
+import io.undertow.io.Sender;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.server.handlers.resource.Resource;
+import io.undertow.server.handlers.resource.ResourceChangeListener;
+import io.undertow.server.handlers.resource.ResourceManager;
+import io.undertow.util.ETag;
+import io.undertow.util.MimeMappings;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.capability.RuntimeCapability;
+import org.jboss.as.server.mgmt.domain.ExtensibleHttpManagement;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.Service;
+import org.jboss.msc.service.ServiceController.Mode;
+import org.jboss.msc.service.ServiceName;
+import org.jboss.msc.service.ServiceTarget;
+import org.jboss.msc.service.StartContext;
+import org.jboss.msc.service.StartException;
+import org.jboss.msc.service.StopContext;
+import org.jboss.msc.value.InjectedValue;
+import org.wildfly.security.http.HttpServerAuthenticationMechanismFactory;
+
+/**
+ * Defines attributes and operations for a secure-deployment.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+final class SecureServerDefinition extends AbstractAdapterConfigurationDefinition {
+
+ public static final String TAG_NAME = "secure-server";
+
+ SecureServerDefinition() {
+ super(TAG_NAME, ALL_ATTRIBUTES, new SecureServerAddHandler(), new SecureServerRemoveHandler(), new SecureServerWriteHandler());
+ }
+
+ /**
+ * A {@link AbstractAdapterConfigurationAddHandler} that exposes a {@link SecureServerDefinition}
+ * as a capability through the installation of a {@link KeycloakHttpAuthenticationFactoryService}.
+ *
+ * @author Pedro Igor
+ */
+ static final class SecureServerAddHandler extends AbstractAdapterConfigurationAddHandler {
+
+ static final String HTTP_SERVER_AUTHENTICATION_CAPABILITY = "org.wildfly.security.http-server-mechanism-factory";
+ static final String HTTP_MANAGEMENT_HTTP_EXTENSIBLE_CAPABILITY = "org.wildfly.management.http.extensible";
+ static RuntimeCapability HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY;
+
+ static {
+ try {
+ HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY = RuntimeCapability
+ .Builder.of(HTTP_SERVER_AUTHENTICATION_CAPABILITY, true, HttpServerAuthenticationMechanismFactory.class)
+ .build();
+ } catch (NoClassDefFoundError ncfe) {
+ // ignore, Elytron not present thus no capability will be published by this resource definition
+ }
+ }
+
+ SecureServerAddHandler() {
+ super(HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY, ALL_ATTRIBUTES);
+ }
+
+ @Override
+ protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.performRuntime(context, operation, model);
+ if (HTTP_SERVER_AUTHENTICATION_RUNTIME_CAPABILITY != null) {
+ installCapability(context, operation);
+ }
+ }
+
+ static void installCapability(OperationContext context, ModelNode operation) throws OperationFailedException {
+ PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
+ String factoryName = pathAddress.getLastElement().getValue();
+ ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
+ boolean publicClient = SecureServerDefinition.PUBLIC_CLIENT.resolveModelAttribute(context, operation).asBoolean(false);
+
+ if (!publicClient) {
+ throw new OperationFailedException("Only public clients are allowed to have their configuration exposed through the management interface");
+ }
+
+ KeycloakHttpAuthenticationFactoryService service = new KeycloakHttpAuthenticationFactoryService(factoryName);
+ ServiceTarget serviceTarget = context.getServiceTarget();
+ InjectedValue injectedValue = new InjectedValue<>();
+ serviceTarget.addService(serviceName.append("http-management-context"), createHttpManagementConfigContextService(factoryName, injectedValue))
+ .addDependency(context.getCapabilityServiceName(HTTP_MANAGEMENT_HTTP_EXTENSIBLE_CAPABILITY, ExtensibleHttpManagement.class), ExtensibleHttpManagement.class, injectedValue).setInitialMode(Mode.ACTIVE).install();
+ serviceTarget.addService(serviceName, service).setInitialMode(Mode.ACTIVE).install();
+ }
+ }
+
+ /**
+ * A {@link AbstractAdapterConfigurationRemoveHandler} that handles the removal of {@link SecureServerDefinition}.
+ *
+ * @author Pedro Igor
+ */
+ static final class SecureServerRemoveHandler extends AbstractAdapterConfigurationRemoveHandler {
+ @Override
+ protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.performRuntime(context, operation, model);
+ PathAddress pathAddress = PathAddress.pathAddress(operation.get(OP_ADDR));
+ String factoryName = pathAddress.getLastElement().getValue();
+ ServiceName serviceName = context.getCapabilityServiceName(HTTP_SERVER_AUTHENTICATION_CAPABILITY, factoryName, HttpServerAuthenticationMechanismFactory.class);
+ context.removeService(serviceName);
+ }
+
+ @Override
+ protected void recoverServices(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+ super.recoverServices(context, operation, model);
+ SecureServerDefinition.SecureServerAddHandler.installCapability(context, operation);
+ }
+ }
+
+ /**
+ * A {@link AbstractAdapterConfigurationWriteAttributeHandler} that updates attributes on a {@link SecureServerDefinition}.
+ *
+ * @author Pedro Igor
+ */
+ static final class SecureServerWriteHandler extends AbstractAdapterConfigurationWriteAttributeHandler {
+ SecureServerWriteHandler() {
+ super(ALL_ATTRIBUTES);
+ }
+ }
+
+ private static Service createHttpManagementConfigContextService(final String factoryName, final InjectedValue httpConfigContext) {
+ final String contextName = "/keycloak/adapter/" + factoryName + "/";
+ return new Service() {
+ public void start(StartContext startContext) throws StartException {
+ ExtensibleHttpManagement extensibleHttpManagement = (ExtensibleHttpManagement)httpConfigContext.getValue();
+ extensibleHttpManagement.addStaticContext(contextName, new ResourceManager() {
+ public Resource getResource(final String path) throws IOException {
+ KeycloakAdapterConfigService adapterConfigService = KeycloakAdapterConfigService.getInstance();
+ final String config = adapterConfigService.getJSON(factoryName);
+
+ if (config == null) {
+ return null;
+ }
+
+ return new Resource() {
+ public String getPath() {
+ return null;
+ }
+
+ public Date getLastModified() {
+ return null;
+ }
+
+ public String getLastModifiedString() {
+ return null;
+ }
+
+ public ETag getETag() {
+ return null;
+ }
+
+ public String getName() {
+ return null;
+ }
+
+ public boolean isDirectory() {
+ return false;
+ }
+
+ public List list() {
+ return Collections.emptyList();
+ }
+
+ public String getContentType(MimeMappings mimeMappings) {
+ return "application/json";
+ }
+
+ public void serve(Sender sender, HttpServerExchange exchange, IoCallback completionCallback) {
+ sender.send(config);
+ }
+
+ public Long getContentLength() {
+ return Long.valueOf((long)config.length());
+ }
+
+ public String getCacheKey() {
+ return null;
+ }
+
+ public File getFile() {
+ return null;
+ }
+
+ public Path getFilePath() {
+ return null;
+ }
+
+ public File getResourceManagerRoot() {
+ return null;
+ }
+
+ public Path getResourceManagerRootPath() {
+ return null;
+ }
+
+ public URL getUrl() {
+ return null;
+ }
+ };
+ }
+
+ public boolean isResourceChangeListenerSupported() {
+ return false;
+ }
+
+ public void registerResourceChangeListener(ResourceChangeListener listener) {
+ }
+
+ public void removeResourceChangeListener(ResourceChangeListener listener) {
+ }
+
+ public void close() throws IOException {
+ }
+ });
+ }
+
+ public void stop(StopContext stopContext) {
+ ((ExtensibleHttpManagement)httpConfigContext.getValue()).removeContext(contextName);
+ }
+
+ public Void getValue() throws IllegalStateException, IllegalArgumentException {
+ return null;
+ }
+ };
+ }
+}
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties
index c9cea77787..f6097ae5cf 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/extension/LocalDescriptions.properties
@@ -20,6 +20,8 @@ keycloak.subsystem.add=Operation Adds Keycloak adapter subsystem
keycloak.subsystem.remove=Operation removes Keycloak adapter subsystem
keycloak.subsystem.realm=A Keycloak realm.
keycloak.subsystem.secure-deployment=A deployment secured by Keycloak.
+keycloak.subsystem.secure-server=A configuration exposed to the server.
+keycloak.subsystem.http-server-mechanism-factory=A http-server-mechanism-factory exposed to the server.
keycloak.realm=A Keycloak realm.
keycloak.realm.add=Add a realm definition to the subsystem.
@@ -90,7 +92,48 @@ keycloak.secure-deployment.token-minimum-time-to-live=The adapter will refresh t
keycloak.secure-deployment.min-time-between-jwks-requests=If adapter recognize token signed by unknown public key, it will try to download new public key from keycloak server. However it won't try to download if already tried it in less than 'min-time-between-jwks-requests' seconds
keycloak.secure-deployment.ignore-oauth-query-parameter=disable query parameter parsing for access_token
+keycloak.secure-server=A deployment secured by Keycloak
+keycloak.secure-server.add=Add a deployment to be secured by Keycloak
+keycloak.secure-server.realm=Keycloak realm
+keycloak.secure-server.remove=Remove a deployment to be secured by Keycloak
+keycloak.secure-server.realm-public-key=Public key of the realm
+keycloak.secure-server.auth-server-url=Base URL of the Realm Auth Server
+keycloak.secure-server.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
+keycloak.secure-server.ssl-required=Specify if SSL is required (valid values are all, external and none)
+keycloak.secure-server.allow-any-hostname=SSL Setting
+keycloak.secure-server.truststore=Truststore used for adapter client HTTPS requests
+keycloak.secure-server.truststore-password=Password of the Truststore
+keycloak.secure-server.connection-pool-size=Connection pool size for the client used by the adapter
+keycloak.secure-server.resource=Application name
+keycloak.secure-server.use-resource-role-mappings=Use resource level permissions from token
+keycloak.secure-server.credentials=Adapter credentials
+keycloak.secure-server.redirect-rewrite-rule=Apply a rewrite rule for the redirect URI
+keycloak.secure-server.bearer-only=Bearer Token Auth only
+keycloak.secure-server.enable-basic-auth=Enable Basic Authentication
+keycloak.secure-server.public-client=Public client
+keycloak.secure-server.enable-cors=Enable Keycloak CORS support
+keycloak.secure-server.autodetect-bearer-only=autodetect bearer-only requests
+keycloak.secure-server.client-keystore=n/a
+keycloak.secure-server.client-keystore-password=n/a
+keycloak.secure-server.client-key-password=n/a
+keycloak.secure-server.cors-max-age=CORS max-age header
+keycloak.secure-server.cors-allowed-headers=CORS allowed headers
+keycloak.secure-server.cors-allowed-methods=CORS allowed methods
+keycloak.secure-server.cors-exposed-headers=CORS exposed headers
+keycloak.secure-server.expose-token=Enable secure URL that exposes access token
+keycloak.secure-server.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
+keycloak.secure-server.always-refresh-token=Refresh token on every single web request
+keycloak.secure-server.register-node-at-startup=Cluster setting
+keycloak.secure-server.register-node-period=how often to re-register node
+keycloak.secure-server.token-store=cookie or session storage for auth session data
+keycloak.secure-server.principal-attribute=token attribute to use to set Principal name
+keycloak.secure-server.turn-off-change-session-id-on-login=The session id is changed by default on a successful login. Change this to true if you want to turn this off
+keycloak.secure-server.token-minimum-time-to-live=The adapter will refresh the token if the current token is expired OR will expire in 'token-minimum-time-to-live' seconds or less
+keycloak.secure-server.min-time-between-jwks-requests=If adapter recognize token signed by unknown public key, it will try to download new public key from keycloak server. However it won't try to download if already tried it in less than 'min-time-between-jwks-requests' seconds
+keycloak.secure-server.ignore-oauth-query-parameter=disable query parameter parsing for access_token
+
keycloak.secure-deployment.credential=Credential value
+keycloak.secure-server.credential=Credential value
keycloak.credential=Credential
keycloak.credential.value=Credential value
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
index d8f5bc3d74..caa147d821 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_1.xsd
@@ -38,6 +38,7 @@
+
@@ -84,7 +85,7 @@
-
+
@@ -99,9 +100,9 @@
-
-
-
+
+
+
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/extension/SubsystemParsingTestCase.java b/adapters/oidc/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/extension/SubsystemParsingTestCase.java
index 9d5f87ab39..4adad9f21a 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/extension/SubsystemParsingTestCase.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/extension/SubsystemParsingTestCase.java
@@ -73,7 +73,7 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
ModelNode deployment = new ModelNode();
deployment.get("realm").set("demo");
deployment.get("resource").set("customer-portal");
- service.addSecureDeployment(deploymentOp, deployment);
+ service.addSecureDeployment(deploymentOp, deployment, false);
addCredential(addr, service, "secret", "secret1");
addCredential(addr, service, "jwt.client-keystore-file", "/tmp/foo.jks");
diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/extension/keycloak-1.1.xml b/adapters/oidc/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/extension/keycloak-1.1.xml
index 246d76855f..fce5c41dae 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/extension/keycloak-1.1.xml
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/extension/keycloak-1.1.xml
@@ -40,6 +40,10 @@
sessionsub
+
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqKoq+a9MgXepmsPJDmo45qswuChW9pWjanX68oIBuI4hGvhQxFHryCow230A+sr7tFdMQMt8f1l/ysmV/fYAuW29WaoY4kI4Ou1yYPuwywKSsxT6PooTs83hKyZ1h4LZMj5DkLGDDDyVRHob2WmPaYg9RGVRw3iGGsD/p+Yb+L/gnBYQnZZ7lYqmN7h36p5CkzzlgXQA1Ha8sQxL+rJNH8+sZm0vBrKsoII3Of7TqHGsm1RwFV3XCuGJ7S61AbjJMXL5DQgJl9Z5scvxGAyoRLKC294UgMnQdzyBTMPw2GybxkRKmiK2KjQKmcopmrJp/Bt6fBR6ZkGSs9qUlxGHgwIDAQAB
+ http://localhost:8180/auth
+ masterweb-console
@@ -69,4 +73,16 @@
/api/$1/
+
+ jboss-infra
+ wildfly-management
+ true
+ EXTERNAL
+ preferred_username
+
+
+ jboss-infra
+ wildfly-console
+ true
+
\ No newline at end of file
diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-wildfly-subsystem/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-wildfly-subsystem/main/module.xml
index 025f15271b..32849fc6f1 100755
--- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-wildfly-subsystem/main/module.xml
+++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/add-ons/keycloak/org/keycloak/keycloak-wildfly-subsystem/main/module.xml
@@ -38,5 +38,9 @@
+
+
+
+
diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index cb25e181fa..db78203044 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -45,9 +45,9 @@
2.53.02.0.1.Final2.1.0.Alpha3
- 2.1.0.Beta1
+ 2.1.0.Alpha21.0.1.Final
- 1.2.0.Beta2
+ 1.2.0.Alpha22.2.21.0.0.Alpha2
From d5ae6bf77aff3ba19414fc273370fd8ed4ccee31 Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Fri, 18 Aug 2017 09:57:29 -0300
Subject: [PATCH 17/26] [KEYCLOAK-5015] - Updating arquillian-wildfly to
2.1.0.Beta1
---
testsuite/integration-arquillian/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index db78203044..78a76480b1 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -45,7 +45,7 @@
2.53.02.0.1.Final2.1.0.Alpha3
- 2.1.0.Alpha2
+ 2.1.0.Beta11.0.1.Final1.2.0.Alpha22.2.2
From 287a86938eafa23c883c2bd82099b558b155cd4a Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Tue, 22 Aug 2017 12:23:52 -0300
Subject: [PATCH 18/26] [KEYCLOAK-5015] - HAL integration tests
---
.../testsuite/pages/AppServerWelcomePage.java | 81 +++++++++++++
.../wildfly-management-realm.json | 68 +++++++++++
.../other/adapters/jboss/wildfly/pom.xml | 2 +-
.../WildflyManagementProtectionTest.java | 109 ++++++++++++++++++
4 files changed, 259 insertions(+), 1 deletion(-)
create mode 100644 testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java
create mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/wildfly-integration/wildfly-management-realm.json
create mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyManagementProtectionTest.java
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java
new file mode 100644
index 0000000000..d7056ee872
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AppServerWelcomePage.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.pages;
+
+import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.testsuite.adapter.page.AppServerContextRoot;
+import org.keycloak.testsuite.auth.page.login.OIDCLogin;
+import org.keycloak.testsuite.util.URLUtils;
+import org.keycloak.testsuite.util.WaitUtils;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+
+/**
+ * @author Pedro Igor
+ */
+public class AppServerWelcomePage extends AppServerContextRoot {
+
+ @Page
+ protected OIDCLogin loginPage;
+
+ @FindBy(xpath = "//a[text() = 'Access Control']")
+ private WebElement accessControlLink;
+
+ @FindBy(xpath = "//a[text() = 'Manage user profile']")
+ private WebElement manageProfileLink;
+
+ @FindBy(xpath = "//div[text() = 'Logout']")
+ private WebElement logoutLink;
+
+ @Override
+ public boolean isCurrent() {
+ return driver.getPageSource().contains("Access Control");
+ }
+
+ public void navigateToConsole() {
+ WaitUtils.pause(2000);
+ URLUtils.navigateToUri(driver, getInjectedUrl().toString() + "/console", true);
+ waitForPageToLoad(driver);
+ }
+
+ public void login(String username, String password) {
+ loginPage.form().waitForLoginButtonPresent();
+ loginPage.form().login(username, password);
+ waitForPageToLoad(driver);
+ }
+
+ public void navigateToAccessControl() {
+ accessControlLink.click();
+ waitForPageToLoad(driver);
+ }
+
+ public void navigateManageProfile() {
+ manageProfileLink.click();
+ waitForPageToLoad(driver);
+ }
+
+ public void logout() {
+ logoutLink.click();
+ waitForPageToLoad(driver);
+ }
+
+ public boolean isLoginPage() {
+ return loginPage.isCurrent();
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/wildfly-integration/wildfly-management-realm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/wildfly-integration/wildfly-management-realm.json
new file mode 100644
index 0000000000..373ca9ab96
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/wildfly-integration/wildfly-management-realm.json
@@ -0,0 +1,68 @@
+{
+ "realm": "jboss-infra",
+ "enabled": true,
+ "sslRequired": "external",
+ "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+ "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+ "requiredCredentials": [
+ "password"
+ ],
+ "users": [
+ {
+ "username": "admin",
+ "enabled": true,
+ "email": "admin@admin.com",
+ "firstName": "Admin",
+ "lastName": "Istrator",
+ "credentials": [
+ {
+ "type": "password",
+ "value": "admin"
+ }
+ ],
+ "realmRoles": [
+ "Administrator"
+ ],
+ "clientRoles": {
+ "realm-management": [
+ "realm-admin"
+ ],
+ "account": [
+ "manage-account"
+ ]
+ }
+ }
+ ],
+ "roles": {
+ "realm": [
+ {
+ "name": "Administrator",
+ "description": "Administrator privileges"
+ }
+ ]
+ },
+ "clients": [
+ {
+ "clientId": "wildfly-console",
+ "enabled": true,
+ "adminUrl": "http://localhost:10190",
+ "baseUrl": "http://localhost:10190",
+ "publicClient": true,
+ "redirectUris": [
+ "http://localhost:10190/*"
+ ],
+ "webOrigins": ["http://localhost:10190"]
+ },
+ {
+ "clientId": "wildfly-management",
+ "secret": "secret",
+ "enabled": true,
+ "baseUrl": "/photoz-restful-api",
+ "publicClient": false,
+ "redirectUris": [
+ "/photoz-restful-api/*"
+ ],
+ "webOrigins" : ["*"]
+ }
+ ]
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml
index 3a6e545cda..061e94e179 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml
@@ -42,7 +42,7 @@
org.wildfly.corewildfly-clitest
- 2.2.0.Final
+ 3.0.0.Beta30
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyManagementProtectionTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyManagementProtectionTest.java
new file mode 100644
index 0000000000..88d4200ea8
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyManagementProtectionTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.adapter.example.authorization;
+
+import static org.junit.Assert.assertTrue;
+import static org.keycloak.testsuite.util.IOUtil.loadRealm;
+
+import java.util.List;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.adapter.AbstractAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.AppServerWelcomePage;
+import org.keycloak.testsuite.util.WaitUtils;
+import org.wildfly.extras.creaper.core.ManagementClient;
+import org.wildfly.extras.creaper.core.online.OnlineManagementClient;
+import org.wildfly.extras.creaper.core.online.OnlineOptions;
+
+/**
+ *
+ * @author Pedro Igor
+ */
+@AppServerContainer("app-server-wildfly")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class WildflyManagementProtectionTest extends AbstractAdapterTest {
+
+ @Page
+ protected AppServerWelcomePage appServerWelcomePage;
+
+ @Page
+ protected AccountUpdateProfilePage accountUpdateProfilePage;
+
+ @Override
+ public void addAdapterTestRealms(List testRealms) {
+ testRealms.add(loadRealm("/wildfly-integration/wildfly-management-realm.json"));
+ }
+
+ @Before
+ public void beforeAuthTest() {
+ super.beforeAuthTest();
+
+ try {
+ OnlineManagementClient clientWorkerNodeClient = ManagementClient.online(OnlineOptions
+ .standalone()
+ .hostAndPort("localhost", 10190)
+ .build());
+
+ // Create a realm for both wildfly console and mgmt interface
+ clientWorkerNodeClient.execute("/subsystem=keycloak/realm=jboss-infra:add(auth-server-url=http://localhost:8180/auth,realm-public-key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB)");
+
+ // Create a secure-deployment in order to protect mgmt interface
+ clientWorkerNodeClient.execute("/subsystem=keycloak/secure-deployment=wildfly-management:add(realm=jboss-infra,resource=wildfly-management,principal-attribute=preferred_username,bearer-only=true,ssl-required=EXTERNAL)");
+
+ // Protect HTTP mgmt interface with Keycloak adapter
+ clientWorkerNodeClient.execute("/core-service=management/management-interface=http-interface:undefine-attribute(name=security-realm)");
+ clientWorkerNodeClient.execute("/subsystem=elytron/http-authentication-factory=keycloak-mgmt-http-authentication:add(security-domain=KeycloakDomain,http-server-mechanism-factory=wildfly-management,mechanism-configurations=[{mechanism-name=KEYCLOAK,mechanism-realm-configurations=[{realm-name=KeycloakOIDCRealm,realm-mapper=keycloak-oidc-realm-mapper}]}])");
+ clientWorkerNodeClient.execute("/core-service=management/management-interface=http-interface:write-attribute(name=http-authentication-factory,value=keycloak-mgmt-http-authentication)");
+ clientWorkerNodeClient.execute("/core-service=management/management-interface=http-interface:write-attribute(name=http-upgrade, value={enabled=true, sasl-authentication-factory=management-sasl-authentication})");
+
+ // Enable RBAC where roles are obtained from the identity
+ clientWorkerNodeClient.execute("/core-service=management/access=authorization:write-attribute(name=provider,value=rbac)");
+ clientWorkerNodeClient.execute("/core-service=management/access=authorization:write-attribute(name=use-identity-roles,value=true)");
+
+ // Create a secure-server in order to publish the wildfly console configuration via mgmt interface
+ clientWorkerNodeClient.execute("/subsystem=keycloak/secure-server=wildfly-console:add(realm=jboss-infra,resource=wildfly-console,public-client=true)");
+
+ // reload
+ clientWorkerNodeClient.execute("reload");
+ } catch (Exception cause) {
+ throw new RuntimeException("Failed to configure app server", cause);
+ }
+ }
+
+ @Test
+ public void testLogin() throws InterruptedException {
+ appServerWelcomePage.navigateToConsole();
+ appServerWelcomePage.login("admin", "admin");
+ WaitUtils.pause(2000);
+ assertTrue(appServerWelcomePage.isCurrent());
+ }
+
+ @Test
+ public void testUserCanAccessAccountService() throws InterruptedException {
+ appServerWelcomePage.navigateToConsole();
+ appServerWelcomePage.login("admin", "admin");
+ WaitUtils.pause(2000);
+ appServerWelcomePage.navigateToAccessControl();
+ appServerWelcomePage.navigateManageProfile();
+ assertTrue(accountUpdateProfilePage.isCurrent());
+ }
+}
From fe5891fbdb195f7a18601c6b530a647e80dba8be Mon Sep 17 00:00:00 2001
From: mposolda
Date: Mon, 21 Aug 2017 21:02:03 +0200
Subject: [PATCH 19/26] KEYCLOAK-5293 Add notBefore to user
---
.../idm/UserRepresentation.java | 9 +++
.../cache/infinispan/UserCacheSession.java | 32 ++++++++-
.../cache/infinispan/entities/CachedUser.java | 7 +-
.../keycloak/models/jpa/JpaUserProvider.java | 13 +++-
.../models/jpa/entities/UserEntity.java | 11 ++++
.../jpa/JpaUserFederatedStorageProvider.java | 14 ++++
.../META-INF/jpa-changelog-3.3.0.xml | 26 ++++++++
.../META-INF/jpa-changelog-master.xml | 1 +
.../models/utils/ModelToRepresentation.java | 2 +
.../models/utils/RepresentationToModel.java | 8 +++
.../org/keycloak/models/UserProvider.java | 2 +
.../UserFederatedStorageProvider.java | 1 +
.../UserNotBeforeFederatedStorage.java | 30 +++++++++
.../exportimport/util/ExportUtils.java | 8 +++
.../keycloak/protocol/oidc/TokenManager.java | 12 +++-
.../managers/AuthenticationManager.java | 6 ++
.../managers/ResourceAdminManager.java | 2 +
.../services/resources/AccountService.java | 6 ++
.../resources/admin/UserResource.java | 2 +
.../keycloak/storage/UserStorageManager.java | 19 ++++++
.../crossdc/SessionExpirationCrossDCTest.java | 65 +++++++++++++++----
.../exportimport/ExportImportUtil.java | 2 +
.../keycloak/testsuite/forms/LogoutTest.java | 22 +++++++
.../src/test/resources/model/testrealm.json | 1 +
.../adapter/AdapterTestStrategy.java | 8 +++
.../FederatedStorageExportImportTest.java | 6 +-
.../testsuite/model/UserModelTest.java | 27 +++++++-
27 files changed, 321 insertions(+), 21 deletions(-)
create mode 100644 model/jpa/src/main/resources/META-INF/jpa-changelog-3.3.0.xml
create mode 100644 server-spi/src/main/java/org/keycloak/storage/federated/UserNotBeforeFederatedStorage.java
diff --git a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
index 4dcea953df..44458fd7e9 100755
--- a/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserRepresentation.java
@@ -55,6 +55,7 @@ public class UserRepresentation {
protected List realmRoles;
protected Map> clientRoles;
protected List clientConsents;
+ protected Integer notBefore;
@Deprecated
protected Map> applicationRoles;
@@ -216,6 +217,14 @@ public class UserRepresentation {
this.clientConsents = clientConsents;
}
+ public Integer getNotBefore() {
+ return notBefore;
+ }
+
+ public void setNotBefore(Integer notBefore) {
+ this.notBefore = notBefore;
+ }
+
@Deprecated
public Map> getApplicationRoles() {
return applicationRoles;
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index 0d971f70b9..390c25c158 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -334,6 +334,8 @@ public class UserCacheSession implements UserCache {
}
protected UserModel cacheUser(RealmModel realm, UserModel delegate, Long revision) {
+ int notBefore = getDelegate().getNotBeforeOfUser(realm, delegate);
+
StorageId storageId = new StorageId(delegate.getId());
CachedUser cached = null;
if (!storageId.isLocal()) {
@@ -343,7 +345,7 @@ public class UserCacheSession implements UserCache {
if (policy != null && policy == UserStorageProviderModel.CachePolicy.NO_CACHE) {
return delegate;
}
- cached = new CachedUser(revision, realm, delegate);
+ cached = new CachedUser(revision, realm, delegate, notBefore);
if (policy == null || policy == UserStorageProviderModel.CachePolicy.DEFAULT) {
cache.addRevisioned(cached, startupRevision);
} else {
@@ -366,7 +368,7 @@ public class UserCacheSession implements UserCache {
}
}
} else {
- cached = new CachedUser(revision, realm, delegate);
+ cached = new CachedUser(revision, realm, delegate, notBefore);
cache.addRevisioned(cached, startupRevision);
}
UserAdapter adapter = new UserAdapter(cached, this, session, realm);
@@ -765,6 +767,32 @@ public class UserCacheSession implements UserCache {
return consentModel;
}
+ @Override
+ public void setNotBeforeForUser(RealmModel realm, UserModel user, int notBefore) {
+ if (!isRegisteredForInvalidation(realm, user.getId())) {
+ UserModel foundUser = getUserById(user.getId(), realm);
+ if (foundUser instanceof UserAdapter) {
+ ((UserAdapter) foundUser).invalidate();
+ }
+ }
+
+ getDelegate().setNotBeforeForUser(realm, user, notBefore);
+
+ }
+
+ @Override
+ public int getNotBeforeOfUser(RealmModel realm, UserModel user) {
+ if (isRegisteredForInvalidation(realm, user.getId())) {
+ return getDelegate().getNotBeforeOfUser(realm, user);
+ }
+
+ UserModel foundUser = getUserById(user.getId(), realm);
+ if (foundUser instanceof UserAdapter) {
+ return ((UserAdapter) foundUser).cached.getNotBefore();
+ } else {
+ return getDelegate().getNotBeforeOfUser(realm, user);
+ }
+ }
@Override
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java
index 1bf6e426a0..68dfc372cb 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUser.java
@@ -45,10 +45,11 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm
private Set requiredActions = new HashSet<>();
private Set roleMappings = new HashSet<>();
private Set groups = new HashSet<>();
+ private int notBefore;
- public CachedUser(Long revision, RealmModel realm, UserModel user) {
+ public CachedUser(Long revision, RealmModel realm, UserModel user, int notBefore) {
super(revision, user.getId());
this.realm = realm.getId();
this.username = user.getUsername();
@@ -71,6 +72,7 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm
groups.add(group.getId());
}
}
+ this.notBefore = notBefore;
}
public String getRealm() {
@@ -129,4 +131,7 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm
return groups;
}
+ public int getNotBefore() {
+ return notBefore;
+ }
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
index b9352c0588..b543d6b2f4 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
@@ -39,7 +39,6 @@ import org.keycloak.models.UserProvider;
import org.keycloak.models.jpa.entities.CredentialAttributeEntity;
import org.keycloak.models.jpa.entities.CredentialEntity;
import org.keycloak.models.jpa.entities.FederatedIdentityEntity;
-import org.keycloak.models.jpa.entities.UserAttributeEntity;
import org.keycloak.models.jpa.entities.UserConsentEntity;
import org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity;
import org.keycloak.models.jpa.entities.UserConsentRoleEntity;
@@ -363,6 +362,18 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
}
+ @Override
+ public void setNotBeforeForUser(RealmModel realm, UserModel user, int notBefore) {
+ UserEntity entity = em.getReference(UserEntity.class, user.getId());
+ entity.setNotBefore(notBefore);
+ }
+
+ @Override
+ public int getNotBeforeOfUser(RealmModel realm, UserModel user) {
+ UserEntity entity = em.getReference(UserEntity.class, user.getId());
+ return entity.getNotBefore();
+ }
+
@Override
public void grantToAllUsers(RealmModel realm, RoleModel role) {
int num = em.createNamedQuery("grantRoleToAllUsers")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
index 50b77607a6..771487f754 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java
@@ -103,6 +103,9 @@ public class UserEntity {
@Column(name="SERVICE_ACCOUNT_CLIENT_LINK")
protected String serviceAccountClientLink;
+ @Column(name="NOT_BEFORE")
+ protected int notBefore;
+
public String getId() {
return id;
}
@@ -224,6 +227,14 @@ public class UserEntity {
this.serviceAccountClientLink = serviceAccountClientLink;
}
+ public int getNotBefore() {
+ return notBefore;
+ }
+
+ public void setNotBefore(int notBefore) {
+ this.notBefore = notBefore;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
index cded4e997b..f6de4312a3 100644
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
@@ -416,6 +416,20 @@ public class JpaUserFederatedStorageProvider implements
}
+ @Override
+ public void setNotBeforeForUser(RealmModel realm, String userId, int notBefore) {
+ // Track it as attribute for now
+ String notBeforeStr = String.valueOf(notBefore);
+ setSingleAttribute(realm, userId, "fedNotBefore", notBeforeStr);
+ }
+
+ @Override
+ public int getNotBeforeOfUser(RealmModel realm, String userId) {
+ MultivaluedHashMap attrs = getAttributes(realm, userId);
+ String notBeforeStr = attrs.getFirst("fedNotBefore");
+
+ return notBeforeStr==null ? 0 : Integer.parseInt(notBeforeStr);
+ }
@Override
public Set getGroups(RealmModel realm, String userId) {
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-3.3.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-3.3.0.xml
new file mode 100644
index 0000000000..c6d201eb49
--- /dev/null
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-3.3.0.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
index ae7d98b4e4..96b9a18dd0 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
@@ -48,4 +48,5 @@
+
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 6b7016ff5f..ef95c0ae6a 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -185,6 +185,8 @@ public class ModelToRepresentation {
rep.setDisableableCredentialTypes(session.userCredentialManager().getDisableableCredentialTypes(realm, user));
rep.setFederationLink(user.getFederationLink());
+ rep.setNotBefore(session.users().getNotBeforeOfUser(realm, user));
+
List reqActions = new ArrayList();
Set requiredActions = user.getRequiredActions();
for (String ra : requiredActions){
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index fe27fae666..3fdddde16a 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1454,6 +1454,11 @@ public class RepresentationToModel {
session.users().addConsent(newRealm, user.getId(), consentModel);
}
}
+
+ if (userRep.getNotBefore() != null) {
+ session.users().setNotBeforeForUser(newRealm, user, userRep.getNotBefore());
+ }
+
if (userRep.getServiceAccountClientId() != null) {
String clientId = userRep.getServiceAccountClientId();
ClientModel client = newRealm.getClientByClientId(clientId);
@@ -2378,6 +2383,9 @@ public class RepresentationToModel {
federatedStorage.addConsent(newRealm, userRep.getId(), consentModel);
}
}
+ if (userRep.getNotBefore() != null) {
+ federatedStorage.setNotBeforeForUser(newRealm, userRep.getId(), userRep.getNotBefore());
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/models/UserProvider.java b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
index 46bb4c3117..c337f3ac87 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
@@ -51,6 +51,8 @@ public interface UserProvider extends Provider,
void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
+ void setNotBeforeForUser(RealmModel realm, UserModel user, int notBefore);
+ int getNotBeforeOfUser(RealmModel realm, UserModel user);
UserModel getServiceAccount(ClientModel client);
List getUsers(RealmModel realm, boolean includeServiceAccounts);
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
index 1d12d3626f..da42c4c868 100755
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
@@ -36,6 +36,7 @@ public interface UserFederatedStorageProvider extends Provider,
UserAttributeFederatedStorage,
UserBrokerLinkFederatedStorage,
UserConsentFederatedStorage,
+ UserNotBeforeFederatedStorage,
UserGroupMembershipFederatedStorage,
UserRequiredActionsFederatedStorage,
UserRoleMappingsFederatedStorage,
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserNotBeforeFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserNotBeforeFederatedStorage.java
new file mode 100644
index 0000000000..4b18026645
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserNotBeforeFederatedStorage.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.storage.federated;
+
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+
+/**
+ * @author Marek Posolda
+ */
+public interface UserNotBeforeFederatedStorage {
+
+ void setNotBeforeForUser(RealmModel realm, String userId, int notBefore);
+ int getNotBeforeOfUser(RealmModel realm, String userId);
+}
diff --git a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
index facce6ca2d..fa1e238b04 100755
--- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
+++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
@@ -530,6 +530,10 @@ public class ExportUtils {
userRep.setClientConsents(consentReps);
}
+ // Not Before
+ int notBefore = session.users().getNotBeforeOfUser(realm, user);
+ userRep.setNotBefore(notBefore);
+
// Service account
if (user.getServiceAccountClientLink() != null) {
String clientInternalId = user.getServiceAccountClientLink();
@@ -717,6 +721,10 @@ public class ExportUtils {
userRep.setClientConsents(consentReps);
}
+ // Not Before
+ int notBefore = session.userFederatedStorage().getNotBeforeOfUser(realm, userRep.getId());
+ userRep.setNotBefore(notBefore);
+
if (options.isGroupsAndRolesIncluded()) {
List groups = new LinkedList<>();
for (GroupModel group : session.userFederatedStorage().getGroups(realm, id)) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index 6a26c692d5..769947a0b8 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -180,6 +180,9 @@ public class TokenManager {
if (oldToken.getIssuedAt() < realm.getNotBefore()) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
}
+ if (oldToken.getIssuedAt() < session.users().getNotBeforeOfUser(realm, user)) {
+ throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
+ }
// recreate token.
@@ -207,9 +210,12 @@ public class TokenManager {
if (!user.isEnabled()) {
return false;
}
+ if (token.getIssuedAt() < session.users().getNotBeforeOfUser(realm, user)) {
+ return false;
+ }
ClientModel client = realm.getClientByClientId(token.getIssuedFor());
- if (client == null || !client.isEnabled()) {
+ if (client == null || !client.isEnabled() || token.getIssuedAt() < client.getNotBefore()) {
return false;
}
@@ -816,9 +822,13 @@ public class TokenManager {
res.setRefreshExpiresIn(refreshToken.getExpiration() - Time.currentTime());
}
}
+
int notBefore = realm.getNotBefore();
if (client.getNotBefore() > notBefore) notBefore = client.getNotBefore();
+ int userNotBefore = session.users().getNotBeforeOfUser(realm, userSession.getUser());
+ if (userNotBefore > notBefore) notBefore = userNotBefore;
res.setNotBeforePolicy(notBefore);
+
return res;
}
}
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index bc28fc4afd..02351204aa 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -817,6 +817,12 @@ public class AuthenticationManager {
return null;
}
+ int userNotBefore = session.users().getNotBeforeOfUser(realm, user);
+ if (token.getIssuedAt() < userNotBefore) {
+ logger.debug("User notBefore newer than token");
+ return null;
+ }
+
UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
if (!isSessionValid(realm, userSession)) {
// Check if accessToken was for the offline session.
diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index 3d71c2a663..dbb0e78c4b 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -107,6 +107,8 @@ public class ResourceAdminManager {
}
public void logoutUser(URI requestUri, RealmModel realm, UserModel user, KeycloakSession keycloakSession) {
+ keycloakSession.users().setNotBeforeForUser(realm, user, Time.currentTime());
+
List userSessions = keycloakSession.sessions().getUserSessions(realm, user);
logoutUserSessions(requestUri, realm, userSessions);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index b814abdb9c..9b26b18c07 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -18,6 +18,7 @@ package org.keycloak.services.resources;
import org.jboss.logging.Logger;
import org.keycloak.common.util.Base64Url;
+import org.keycloak.common.util.Time;
import org.keycloak.common.util.UriUtils;
import org.keycloak.credential.CredentialModel;
import org.keycloak.events.Details;
@@ -505,6 +506,11 @@ public class AccountService extends AbstractSecuredLocalService {
csrfCheck(stateChecker);
UserModel user = auth.getUser();
+
+ // Rather decrease time a bit. To avoid situation when user is immediatelly redirected to login screen, then automatically authenticated (eg. with Kerberos) and then seeing issues due the stale token
+ // as time on the token will be same like notBefore
+ session.users().setNotBeforeForUser(realm, user, Time.currentTime() - 1);
+
List userSessions = session.sessions().getUserSessions(realm, user);
for (UserSessionModel userSession : userSessions) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
index fbd318ae74..21943ccd79 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java
@@ -508,6 +508,8 @@ public class UserResource {
public void logout() {
auth.users().requireManage(user);
+ session.users().setNotBeforeForUser(realm, user, Time.currentTime());
+
List userSessions = session.sessions().getUserSessions(realm, user);
for (UserSessionModel userSession : userSessions) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, true);
diff --git a/services/src/main/java/org/keycloak/storage/UserStorageManager.java b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
index 2baeb8ceb2..8c5b633f89 100755
--- a/services/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/services/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -231,6 +231,25 @@ public class UserStorageManager implements UserProvider, OnUserCache, OnCreateCo
}
}
+ @Override
+ public void setNotBeforeForUser(RealmModel realm, UserModel user, int notBefore) {
+ if (StorageId.isLocalStorage(user)) {
+ localStorage().setNotBeforeForUser(realm, user, notBefore);
+ } else {
+ getFederatedStorage().setNotBeforeForUser(realm, user.getId(), notBefore);
+ }
+ }
+
+ @Override
+ public int getNotBeforeOfUser(RealmModel realm, UserModel user) {
+ if (StorageId.isLocalStorage(user)) {
+ return localStorage().getNotBeforeOfUser(realm, user);
+
+ } else {
+ return getFederatedStorage().getNotBeforeOfUser(realm, user.getId());
+ }
+ }
+
/**
* Allows a UserStorageProvider to proxy and/or synchronize an imported user.
*
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/SessionExpirationCrossDCTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/SessionExpirationCrossDCTest.java
index 19e45d1b62..a7f955924e 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/SessionExpirationCrossDCTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/crossdc/SessionExpirationCrossDCTest.java
@@ -18,6 +18,9 @@
package org.keycloak.testsuite.crossdc;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.ws.rs.NotFoundException;
import org.hamcrest.Matchers;
@@ -101,7 +104,7 @@ public class SessionExpirationCrossDCTest extends AbstractAdminCrossDCTest {
@JmxInfinispanCacheStatistics(dc=DC.FIRST, dcNodeIndex=0, cacheName=InfinispanConnectionProvider.SESSION_CACHE_NAME) InfinispanStatistics cacheDc1Statistics,
@JmxInfinispanCacheStatistics(dc=DC.SECOND, dcNodeIndex=0, cacheName=InfinispanConnectionProvider.SESSION_CACHE_NAME) InfinispanStatistics cacheDc2Statistics,
@JmxInfinispanChannelStatistics() InfinispanStatistics channelStatisticsCrossDc) throws Exception {
- createInitialSessions(InfinispanConnectionProvider.SESSION_CACHE_NAME, false, cacheDc1Statistics, cacheDc2Statistics);
+ createInitialSessions(InfinispanConnectionProvider.SESSION_CACHE_NAME, false, cacheDc1Statistics, cacheDc2Statistics, true);
// log.infof("Sleeping!");
// Thread.sleep(10000000);
@@ -118,7 +121,7 @@ public class SessionExpirationCrossDCTest extends AbstractAdminCrossDCTest {
// Return last used accessTokenResponse
- private OAuthClient.AccessTokenResponse createInitialSessions(String cacheName, boolean offline, InfinispanStatistics cacheDc1Statistics, InfinispanStatistics cacheDc2Statistics) throws Exception {
+ private List createInitialSessions(String cacheName, boolean offline, InfinispanStatistics cacheDc1Statistics, InfinispanStatistics cacheDc2Statistics, boolean includeRemoteStats) throws Exception {
// Enable second DC
enableDcOnLoadBalancer(DC.SECOND);
@@ -137,9 +140,9 @@ public class SessionExpirationCrossDCTest extends AbstractAdminCrossDCTest {
oauth.scope(OAuth2Constants.OFFLINE_ACCESS);
}
- OAuthClient.AccessTokenResponse lastAccessTokenResponse = null;
+ List responses = new ArrayList<>();
for (int i=0 ; i responses = createInitialSessions(InfinispanConnectionProvider.SESSION_CACHE_NAME, false, cacheDc1Statistics, cacheDc2Statistics, false);
+
+ // Kill node2 now. Around 10 sessions (half of SESSIONS_COUNT) will be lost on Keycloak side. But not on infinispan side
+ stopBackendNode(DC.FIRST, 1);
+
+ channelStatisticsCrossDc.reset();
+
+ // Increase offset a bit to ensure logout happens later then token issued time
+ setTimeOffset(10);
+
+ // Logout user
+ ApiUtil.findUserByUsernameId(getAdminClient().realm(REALM_NAME), "login-test").logout();
+
+ // Assert it's not possible to refresh sessions. Works because user.notBefore
+ int i = 0;
+ for (OAuthClient.AccessTokenResponse response : responses) {
+ i++;
+ OAuthClient.AccessTokenResponse refreshTokenResponse = oauth.doRefreshTokenRequest(response.getRefreshToken(), "password");
+ Assert.assertNull("Failed in iteration " + i, refreshTokenResponse.getRefreshToken());
+ Assert.assertNotNull("Failed in iteration " + i, refreshTokenResponse.getError());
+ }
+ }
+
// AUTH SESSIONS
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java
index 677430d23a..d1c70075c3 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java
@@ -154,6 +154,8 @@ public class ExportImportUtil {
Assert.assertNull(realmRsc.users().get(wburke.getId()).roles().getAll().getRealmMappings());
+ Assert.assertEquals((Object) 159, wburke.getNotBefore());
+
UserRepresentation loginclient = findByUsername(realmRsc, "loginclient");
// user with creation timestamp as string in import
Assert.assertEquals(new Long(123655), loginclient.getCreatedTimestamp());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java
index 7fc3f743d0..a3a03cbe68 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java
@@ -21,8 +21,11 @@ import org.junit.Rule;
import org.junit.Test;
import org.keycloak.events.Details;
import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
+import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.LoginPage;
@@ -210,4 +213,23 @@ public class LogoutTest extends AbstractTestRealmKeycloakTest {
events.expectLogout(sessionId2).removeDetail(Details.REDIRECT_URI).assertEvent();
}
+ @Test
+ public void logoutUserByAdmin() {
+ loginPage.open();
+ loginPage.login("test-user@localhost", "password");
+ assertTrue(appPage.isCurrent());
+ String sessionId = events.expectLogin().assertEvent().getSessionId();
+
+ UserRepresentation user = ApiUtil.findUserByUsername(adminClient.realm("test"), "test-user@localhost");
+ Assert.assertEquals((Object) 0, user.getNotBefore());
+
+ adminClient.realm("test").users().get(user.getId()).logout();
+
+ user = adminClient.realm("test").users().get(user.getId()).toRepresentation();
+ Assert.assertTrue(user.getNotBefore() > 0);
+
+ loginPage.open();
+ loginPage.assertCurrent();
+ }
+
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json
index fb1a7e0002..a0c5b3011e 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json
@@ -120,6 +120,7 @@
"username": "wburke",
"enabled": true,
"createdTimestamp" : 123654,
+ "notBefore": 159,
"attributes": {
"email": "bburke@redhat.com"
},
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index e006820549..98215f7bfb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -126,6 +126,14 @@ public class AdapterTestStrategy extends ExternalResource {
protected void after() {
super.after();
webRule.after();
+
+ // Revert notBefore
+ KeycloakSession session = keycloakRule.startSession();
+ RealmModel realm = session.realms().getRealmByName("demo");
+ UserModel user = session.users().getUserByUsername("bburke@redhat.com", realm);
+ session.users().setNotBeforeForUser(realm, user, 0);
+ session.getTransactionManager().commit();
+ session.close();
}
public void testSavedPostRequest() throws Exception {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java
index 8a1bf5dbeb..a1e4411359 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/FederatedStorageExportImportTest.java
@@ -137,7 +137,7 @@ public class FederatedStorageExportImportTest {
Assert.assertEquals(1, session.userFederatedStorage().getStoredUsersCount(realm));
MultivaluedHashMap attributes = session.userFederatedStorage().getAttributes(realm, userId);
- Assert.assertEquals(2, attributes.size());
+ Assert.assertEquals(3, attributes.size());
Assert.assertEquals("value1", attributes.getFirst("single1"));
Assert.assertTrue(attributes.getList("list1").contains("1"));
Assert.assertTrue(attributes.getList("list1").contains("2"));
@@ -174,6 +174,7 @@ public class FederatedStorageExportImportTest {
session.userFederatedStorage().createCredential(realm, userId, credential);
session.userFederatedStorage().grantRole(realm, userId, role);
session.userFederatedStorage().joinGroup(realm, userId, group);
+ session.userFederatedStorage().setNotBeforeForUser(realm, userId, 50);
keycloakRule.stopSession(session, true);
@@ -203,13 +204,14 @@ public class FederatedStorageExportImportTest {
Assert.assertEquals(1, session.userFederatedStorage().getStoredUsersCount(realm));
MultivaluedHashMap attributes = session.userFederatedStorage().getAttributes(realm, userId);
- Assert.assertEquals(2, attributes.size());
+ Assert.assertEquals(3, attributes.size());
Assert.assertEquals("value1", attributes.getFirst("single1"));
Assert.assertTrue(attributes.getList("list1").contains("1"));
Assert.assertTrue(attributes.getList("list1").contains("2"));
Assert.assertTrue(session.userFederatedStorage().getRequiredActions(realm, userId).contains("UPDATE_PASSWORD"));
Assert.assertTrue(session.userFederatedStorage().getRoleMappings(realm, userId).contains(role));
Assert.assertTrue(session.userFederatedStorage().getGroups(realm, userId).contains(group));
+ Assert.assertEquals(50, session.userFederatedStorage().getNotBeforeOfUser(realm, userId));
List creds = session.userFederatedStorage().getStoredCredentials(realm, userId);
Assert.assertEquals(1, creds.size());
Assert.assertTrue(getHashProvider(session, realm.getPasswordPolicy()).verify("password", creds.get(0)));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
index 191a39af89..4e0dca51c1 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
@@ -241,7 +241,7 @@ public class UserModelTest extends AbstractModelTest {
@Test
public void testUpdateUserSingleAttribute() {
Map> expected = ImmutableMap.of(
- "key1", Arrays.asList("value3"),
+ "key1", Arrays.asList("value3"),
"key2", Arrays.asList("value2"));
RealmModel realm = realmManager.createRealm("original");
@@ -398,6 +398,31 @@ public class UserModelTest extends AbstractModelTest {
Assert.assertFalse(realm2User1.hasRole(role1));
}
+ @Test
+ public void testUserNotBefore() throws Exception {
+ RealmModel realm = realmManager.createRealm("original");
+
+ UserModel user1 = session.users().addUser(realm, "user1");
+ session.users().setNotBeforeForUser(realm, user1, 10);
+
+ commit();
+
+ realm = realmManager.getRealmByName("original");
+ user1 = session.users().getUserByUsername("user1", realm);
+ int notBefore = session.users().getNotBeforeOfUser(realm, user1);
+ Assert.assertEquals(10, notBefore);
+
+ // Try to update
+ session.users().setNotBeforeForUser(realm, user1, 20);
+
+ commit();
+
+ realm = realmManager.getRealmByName("original");
+ user1 = session.users().getUserByUsername("user1", realm);
+ notBefore = session.users().getNotBeforeOfUser(realm, user1);
+ Assert.assertEquals(20, notBefore);
+ }
+
public static void assertEquals(UserModel expected, UserModel actual) {
Assert.assertEquals(expected.getUsername(), actual.getUsername());
Assert.assertEquals(expected.getCreatedTimestamp(), actual.getCreatedTimestamp());
From 44efe24bf0a3738914309eab69d42a848df1eb02 Mon Sep 17 00:00:00 2001
From: mhajas
Date: Wed, 23 Aug 2017 12:34:19 +0200
Subject: [PATCH 20/26] KEYCLOAK-4393 Remove forgotten class
---
.../example/WildflyBasicAuthExampleAdapterTest.java | 12 ------------
1 file changed, 12 deletions(-)
delete mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyBasicAuthExampleAdapterTest.java
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyBasicAuthExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyBasicAuthExampleAdapterTest.java
deleted file mode 100644
index 878f337cbe..0000000000
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyBasicAuthExampleAdapterTest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.testsuite.adapter.example;
-
-import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-
-/**
- *
- * @author tkyjovsk
- */
-@AppServerContainer("app-server-wildfly")
-public class WildflyBasicAuthExampleAdapterTest extends AbstractBasicAuthExampleAdapterTest {
-
-}
From eb5a5023c6c30e161d8363856702be801caff9ce Mon Sep 17 00:00:00 2001
From: Stan Silvert
Date: Wed, 23 Aug 2017 09:55:19 -0400
Subject: [PATCH 21/26] KEYCLOAK-5266: Component numberOfPages in clients view
is missing (#4411)
---
.../base/admin/resources/js/controllers/clients.js | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 33cb93be30..e3d03b5526 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -730,12 +730,17 @@ module.controller('ClientImportCtrl', function($scope, $location, $upload, realm
module.controller('ClientListCtrl', function($scope, realm, Client, serverInfo, $route, Dialog, Notifications, filterFilter) {
$scope.realm = realm;
- $scope.clients = Client.query({realm: realm.realm, viewableOnly: true});
+ $scope.clients = [];
$scope.currentPage = 1;
$scope.currentPageInput = 1;
+ $scope.numberOfPages = 1;
$scope.pageSize = 20;
- $scope.numberOfPages = Math.ceil($scope.clients.length/$scope.pageSize);
-
+
+ Client.query({realm: realm.realm, viewableOnly: true}).$promise.then(function(clients) {
+ $scope.numberOfPages = Math.ceil(clients.length/$scope.pageSize);
+ $scope.clients = clients;
+ });
+
$scope.$watch('search', function (newVal, oldVal) {
$scope.filtered = filterFilter($scope.clients, newVal);
$scope.totalItems = $scope.filtered.length;
@@ -743,7 +748,7 @@ module.controller('ClientListCtrl', function($scope, realm, Client, serverInfo,
$scope.currentPage = 1;
$scope.currentPageInput = 1;
}, true);
-
+
$scope.removeClient = function(client) {
Dialog.confirmDelete(client.clientId, 'client', function() {
Client.remove({
From 010dd5709ce5522636064c61f4a0296e9d0ce121 Mon Sep 17 00:00:00 2001
From: Stan Silvert
Date: Wed, 23 Aug 2017 09:55:49 -0400
Subject: [PATCH 22/26] KEYCLOAK-5286: js error on save in
client/mappers/details screen (#4409)
---
.../theme/base/admin/resources/js/controllers/clients.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index e3d03b5526..76c9a9b701 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -1803,7 +1803,7 @@ module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo
ClientProtocolMapper.update({
realm : realm.realm,
client: client.id,
- id : mapper.id
+ id : $scope.model.mapper.id
}, $scope.model.mapper, function() {
$scope.model.changed = false;
mapper = angular.copy($scope.mapper);
From 245f6c0c84a1bb3c2532c9a5cd9e9227db49c137 Mon Sep 17 00:00:00 2001
From: Stan Silvert
Date: Wed, 23 Aug 2017 09:56:28 -0400
Subject: [PATCH 23/26] KEYCLOAK-5232: 'undefined' in allowed protocol mappers
field (#4398)
---
.../admin/resources/js/controllers/realm.js | 3 ++-
.../theme/base/admin/resources/js/services.js | 19 +++++++++++++++++++
.../templates/kc-component-config.html | 4 +---
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 0b48d4c7a2..2644379891 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -2513,6 +2513,7 @@ module.controller('ClientRegPolicyDetailCtrl', function($scope, realm, clientReg
if ($scope.providerType.properties) {
ComponentUtils.addLastEmptyValueToMultivaluedLists($scope.providerType.properties, $scope.instance.config);
+ ComponentUtils.addMvOptionsToMultivaluedLists($scope.providerType.properties);
}
var oldCopy = angular.copy($scope.instance);
@@ -2523,7 +2524,7 @@ module.controller('ClientRegPolicyDetailCtrl', function($scope, realm, clientReg
$scope.changed = true;
}
}, true);
-
+
$scope.reset = function() {
$route.reload();
};
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/services.js b/themes/src/main/resources/theme/base/admin/resources/js/services.js
index fca7b334f1..b084a4fc08 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -232,6 +232,25 @@ module.factory('ComponentUtils', function() {
}
}
}
+
+ // Allows you to use ui-select2 with tag.
+ // In HTML you will then use property.mvOptions like this:
+ //
-
+
From b4530cfbe9ebb1d005cbeec8f17df2c556733a5e Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Wed, 23 Aug 2017 13:30:21 -0300
Subject: [PATCH 24/26] fixing policy enforcer /*
---
.../java/org/keycloak/adapters/authorization/PathMatcher.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathMatcher.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathMatcher.java
index 9efa614573..c8bce94592 100644
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathMatcher.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathMatcher.java
@@ -89,7 +89,7 @@ class PathMatcher {
pathString = "/";
}
- if (matchingUri.equals(targetUri)) {
+ if (matchingUri.equals(targetUri) || pathString.equals(targetUri)) {
cache.put(targetUri, entry);
return entry;
}
From 3ff38e22cf839182b0f9ef9fe12e0bf9c62cf9f1 Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Wed, 23 Aug 2017 15:11:48 -0300
Subject: [PATCH 25/26] [KEYCLOAK-4639] - Invalidating resource query by owner
cache
---
.../infinispan/authorization/ResourceAdapter.java | 10 +++++-----
.../authorization/StoreFactoryCacheManager.java | 6 +++---
.../authorization/StoreFactoryCacheSession.java | 8 ++++----
.../authorization/events/ResourceUpdatedEvent.java | 6 ++++--
4 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/ResourceAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/ResourceAdapter.java
index dc721b7112..5e9b7d3431 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/ResourceAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/ResourceAdapter.java
@@ -46,7 +46,7 @@ public class ResourceAdapter implements Resource, CachedModel {
@Override
public Resource getDelegateForUpdate() {
if (updated == null) {
- cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getType(), cached.getUri(), cached.getScopesIds(), cached.getResourceServerId());
+ cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getType(), cached.getUri(), cached.getScopesIds(), cached.getResourceServerId(), cached.getOwner());
updated = cacheSession.getResourceStoreDelegate().findById(cached.getId(), cached.getResourceServerId());
if (updated == null) throw new IllegalStateException("Not found in database");
}
@@ -95,7 +95,7 @@ public class ResourceAdapter implements Resource, CachedModel {
@Override
public void setName(String name) {
getDelegateForUpdate();
- cacheSession.registerResourceInvalidation(cached.getId(), name, cached.getType(), cached.getUri(), cached.getScopesIds(), cached.getResourceServerId());
+ cacheSession.registerResourceInvalidation(cached.getId(), name, cached.getType(), cached.getUri(), cached.getScopesIds(), cached.getResourceServerId(), cached.getOwner());
updated.setName(name);
}
@@ -127,7 +127,7 @@ public class ResourceAdapter implements Resource, CachedModel {
@Override
public void setUri(String uri) {
getDelegateForUpdate();
- cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getType(), uri, cached.getScopesIds(), cached.getResourceServerId());
+ cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getType(), uri, cached.getScopesIds(), cached.getResourceServerId(), cached.getOwner());
updated.setUri(uri);
}
@@ -140,7 +140,7 @@ public class ResourceAdapter implements Resource, CachedModel {
@Override
public void setType(String type) {
getDelegateForUpdate();
- cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), type, cached.getUri(), cached.getScopesIds(), cached.getResourceServerId());
+ cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), type, cached.getUri(), cached.getScopesIds(), cached.getResourceServerId(), cached.getOwner());
updated.setType(type);
}
@@ -168,7 +168,7 @@ public class ResourceAdapter implements Resource, CachedModel {
@Override
public void updateScopes(Set scopes) {
getDelegateForUpdate();
- cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getType(), cached.getUri(), scopes.stream().map(scope1 -> scope1.getId()).collect(Collectors.toSet()), cached.getResourceServerId());
+ cacheSession.registerResourceInvalidation(cached.getId(), cached.getName(), cached.getType(), cached.getUri(), scopes.stream().map(scope1 -> scope1.getId()).collect(Collectors.toSet()), cached.getResourceServerId(), cached.getOwner());
updated.updateScopes(scopes);
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java
index 63eb8a73da..e9853d68ba 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheManager.java
@@ -75,9 +75,10 @@ public class StoreFactoryCacheManager extends CacheManager {
addInvalidations(InScopePredicate.create().scope(id), invalidations);
}
- public void resourceUpdated(String id, String name, String type, String uri, Set scopes, String serverId, Set invalidations) {
+ public void resourceUpdated(String id, String name, String type, String uri, Set scopes, String serverId, String owner, Set invalidations) {
invalidations.add(id);
invalidations.add(StoreFactoryCacheSession.getResourceByNameCacheKey(name, serverId));
+ invalidations.add(StoreFactoryCacheSession.getResourceByOwnerCacheKey(owner, serverId));
if (type != null) {
invalidations.add(StoreFactoryCacheSession.getResourceByTypeCacheKey(type, serverId));
@@ -97,8 +98,7 @@ public class StoreFactoryCacheManager extends CacheManager {
}
public void resourceRemoval(String id, String name, String type, String uri, String owner, Set scopes, String serverId, Set invalidations) {
- resourceUpdated(id, name, type, uri, scopes, serverId, invalidations);
- invalidations.add(StoreFactoryCacheSession.getResourceByOwnerCacheKey(owner, serverId));
+ resourceUpdated(id, name, type, uri, scopes, serverId, owner, invalidations);
addInvalidations(InResourcePredicate.create().resource(id), invalidations);
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java
index a169235643..27bacc45b0 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/StoreFactoryCacheSession.java
@@ -245,12 +245,12 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
invalidationEvents.add(ScopeUpdatedEvent.create(id, name, serverId));
}
- public void registerResourceInvalidation(String id, String name, String type, String uri, Set scopes, String serverId) {
- cache.resourceUpdated(id, name, type, uri, scopes, serverId, invalidations);
+ public void registerResourceInvalidation(String id, String name, String type, String uri, Set scopes, String serverId, String owner) {
+ cache.resourceUpdated(id, name, type, uri, scopes, serverId, owner, invalidations);
ResourceAdapter adapter = managedResources.get(id);
if (adapter != null) adapter.invalidateFlag();
- invalidationEvents.add(ResourceUpdatedEvent.create(id, name, type, uri, scopes, serverId));
+ invalidationEvents.add(ResourceUpdatedEvent.create(id, name, type, uri, scopes, serverId, owner));
}
public void registerPolicyInvalidation(String id, String name, Set resources, Set scopes, String serverId) {
@@ -509,7 +509,7 @@ public class StoreFactoryCacheSession implements CachedStoreFactoryProvider {
@Override
public Resource create(String name, ResourceServer resourceServer, String owner) {
Resource resource = getResourceStoreDelegate().create(name, resourceServer, owner);
- registerResourceInvalidation(resource.getId(), resource.getName(), resource.getType(), resource.getUri(), resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet()), resourceServer.getId());
+ registerResourceInvalidation(resource.getId(), resource.getName(), resource.getType(), resource.getUri(), resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toSet()), resourceServer.getId(), resource.getOwner());
return resource;
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/ResourceUpdatedEvent.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/ResourceUpdatedEvent.java
index cc30f230d9..3f85a6d5b0 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/ResourceUpdatedEvent.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/authorization/events/ResourceUpdatedEvent.java
@@ -33,8 +33,9 @@ public class ResourceUpdatedEvent extends InvalidationEvent implements Authoriza
private String type;
private String uri;
private Set scopes;
+ private String owner;
- public static ResourceUpdatedEvent create(String id, String name, String type, String uri, Set scopes, String serverId) {
+ public static ResourceUpdatedEvent create(String id, String name, String type, String uri, Set scopes, String serverId, String owner) {
ResourceUpdatedEvent event = new ResourceUpdatedEvent();
event.id = id;
event.name = name;
@@ -42,6 +43,7 @@ public class ResourceUpdatedEvent extends InvalidationEvent implements Authoriza
event.uri = uri;
event.scopes = scopes;
event.serverId = serverId;
+ event.owner = owner;
return event;
}
@@ -57,6 +59,6 @@ public class ResourceUpdatedEvent extends InvalidationEvent implements Authoriza
@Override
public void addInvalidations(StoreFactoryCacheManager cache, Set invalidations) {
- cache.resourceUpdated(id, name, type, uri, scopes, serverId, invalidations);
+ cache.resourceUpdated(id, name, type, uri, scopes, serverId, owner, invalidations);
}
}
From 16305418f0fa5de1eaea5b83bd000668966f83bf Mon Sep 17 00:00:00 2001
From: Pedro Igor
Date: Wed, 23 Aug 2017 15:13:24 -0300
Subject: [PATCH 26/26] [KEYCLOAK-4915] - Unable to update resource permission
without changing applied policies
---
.../theme/base/admin/resources/js/authz/authz-controller.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index 14c9392af4..037a0c3bf2 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -971,12 +971,12 @@ module.controller('ResourceServerPolicyResourceDetailCtrl', function($scope, $ro
$scope.applyToResourceTypeFlag = true;
}
- $scope.selectedPolicies = [];
ResourceServerPermission.associatedPolicies({
realm : $route.current.params.realm,
client : client.id,
id : policy.id
}, function(policies) {
+ $scope.selectedPolicies = [];
for (i = 0; i < policies.length; i++) {
policies[i].text = policies[i].name;
$scope.selectedPolicies.push(policies[i]);