KEYCLOAK-7123: l10n dropdowns (#5170)

* KEYCLOAK-7196: Add kc_locale to keycloak.js

* KEYCLOAK-7123: Localization dropdowns

* Update keycloak-service to latest keycloak.js
This commit is contained in:
Stan Silvert 2018-04-25 15:04:12 -04:00 committed by GitHub
parent fe2ae6ec68
commit 35154db50f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 577 additions and 534 deletions

View file

@ -1,495 +1,495 @@
/*
* MIT License
*
* Copyright 2017 Brett Epps <https://github.com/eppsilon>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
export as namespace Keycloak;
export = Keycloak;
/**
* Creates a new Keycloak client instance.
* @param config Path to a JSON config file or a plain config object.
*/
declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance;
declare namespace Keycloak {
type KeycloakAdapterName = 'cordova'|'default' | any;
type KeycloakOnLoad = 'login-required'|'check-sso';
type KeycloakResponseMode = 'query'|'fragment';
type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
type KeycloakFlow = 'standard'|'implicit'|'hybrid';
interface KeycloakInitOptions {
/**
* @private Undocumented.
*/
useNonce?: boolean;
/**
* Allows to use different adapter:
*
* - {string} default - using browser api for redirects
* - {string} cordova - using cordova plugins
* - {function} - allows to provide custom function as adapter.
*/
adapter?: KeycloakAdapterName;
/**
* Specifies an action to do on load.
*/
onLoad?: KeycloakOnLoad;
/**
* Set an initial value for the token.
*/
token?: string;
/**
* Set an initial value for the refresh token.
*/
refreshToken?: string;
/**
* Set an initial value for the id token (only together with `token` or
* `refreshToken`).
*/
idToken?: string;
/**
* Set an initial value for skew between local time and Keycloak server in
* seconds (only together with `token` or `refreshToken`).
*/
timeSkew?: number;
/**
* Set to enable/disable monitoring login state.
* @default true
*/
checkLoginIframe?: boolean;
/**
* Set the interval to check login state (in seconds).
* @default 5
*/
checkLoginIframeInterval?: number;
/**
* Set the OpenID Connect response mode to send to Keycloak upon login.
* @default fragment After successful authentication Keycloak will redirect
* to JavaScript application with OpenID Connect parameters
* added in URL fragment. This is generally safer and
* recommended over query.
*/
responseMode?: KeycloakResponseMode;
/**
* Set the OpenID Connect flow.
* @default standard
*/
flow?: KeycloakFlow;
}
interface KeycloakLoginOptions {
/**
* @private Undocumented.
*/
scope?: string;
/**
* Specifies the uri to redirect to after login.
*/
redirectUri?: string;
/**
* By default the login screen is displayed if the user is not logged into
* Keycloak. To only authenticate to the application if the user is already
* logged in and not display the login page if the user is not logged in, set
* this option to `'none'`. To always require re-authentication and ignore
* SSO, set this option to `'login'`.
*/
prompt?: 'none'|'login';
/**
* If value is `'register'` then user is redirected to registration page,
* otherwise to login page.
*/
action?: 'register';
/**
* Used just if user is already authenticated. Specifies maximum time since
* the authentication of user happened. If user is already authenticated for
* longer time than `'maxAge'`, the SSO is ignored and he will need to
* authenticate again.
*/
maxAge?: number;
/**
* Used to pre-fill the username/email field on the login form.
*/
loginHint?: string;
/**
* Used to tell Keycloak which IDP the user wants to authenticate with.
*/
idpHint?: string;
/**
* Sets the 'ui_locales' query param in compliance with section 3.1.2.1
* of the OIDC 1.0 specification.
*/
locale?: string;
/**
* Specifies the desired Keycloak locale for the UI. This differs from
* the locale param in that it tells the Keycloak server to set a cookie and update
* the user's profile to a new preferred locale.
*/
kcLocale?: string;
}
type KeycloakPromiseCallback<T> = (result: T) => void;
interface KeycloakPromise<TSuccess, TError> {
/**
* Function to call if the promised action succeeds.
*/
success(callback: KeycloakPromiseCallback<TSuccess>): KeycloakPromise<TSuccess, TError>;
/**
* Function to call if the promised action throws an error.
*/
error(callback: KeycloakPromiseCallback<TError>): KeycloakPromise<TSuccess, TError>;
}
interface KeycloakError {
error: string;
error_description: string;
}
interface KeycloakAdapter {
login(options?: KeycloakLoginOptions): KeycloakPromise<void, void>;
logout(options?: any): KeycloakPromise<void, void>;
register(options?: KeycloakLoginOptions): KeycloakPromise<void, void>;
accountManagement(): KeycloakPromise<void, void>;
redirectUri(options: { redirectUri: string; }, encodeHash: boolean): string;
}
interface KeycloakProfile {
id?: string;
username?: string;
email?: string;
firstName?: string;
lastName?: string;
enabled?: boolean;
emailVerified?: boolean;
totp?: boolean;
createdTimestamp?: number;
}
// export interface KeycloakUserInfo {}
/**
* A client for the Keycloak authentication server.
* @see {@link https://keycloak.gitbooks.io/securing-client-applications-guide/content/topics/oidc/javascript-adapter.html|Keycloak JS adapter documentation}
*/
interface KeycloakInstance {
/**
* Is true if the user is authenticated, false otherwise.
*/
authenticated?: boolean;
/**
* The user id.
*/
subject?: string;
/**
* Response mode passed in init (default value is `'fragment'`).
*/
responseMode?: KeycloakResponseMode;
/**
* Response type sent to Keycloak with login requests. This is determined
* based on the flow value used during initialization, but can be overridden
* by setting this value.
*/
responseType?: KeycloakResponseType;
/**
* Flow passed in init.
*/
flow?: KeycloakFlow;
/**
* The realm roles associated with the token.
*/
realmAccess?: { roles: string[] };
/**
* The resource roles associated with the token.
*/
resourceAccess?: string[];
/**
* The base64 encoded token that can be sent in the Authorization header in
* requests to services.
*/
token?: string;
/**
* The parsed token as a JavaScript object.
*/
tokenParsed?: {
exp?: number;
iat?: number;
nonce?: string;
sub?: string;
session_state?: string;
realm_access?: { roles: string[] };
resource_access?: string[];
};
/**
* The base64 encoded refresh token that can be used to retrieve a new token.
*/
refreshToken?: string;
/**
* The parsed refresh token as a JavaScript object.
*/
refreshTokenParsed?: { nonce?: string };
/**
* The base64 encoded ID token.
*/
idToken?: string;
/**
* The parsed id token as a JavaScript object.
*/
idTokenParsed?: { nonce?: string };
/**
* The estimated time difference between the browser time and the Keycloak
* server in seconds. This value is just an estimation, but is accurate
* enough when determining if a token is expired or not.
*/
timeSkew?: number;
/**
* @private Undocumented.
*/
loginRequired?: boolean;
/**
* @private Undocumented.
*/
authServerUrl?: string;
/**
* @private Undocumented.
*/
realm?: string;
/**
* @private Undocumented.
*/
clientId?: string;
/**
* @private Undocumented.
*/
clientSecret?: string;
/**
* @private Undocumented.
*/
redirectUri?: string;
/**
* @private Undocumented.
*/
sessionId?: string;
/**
* @private Undocumented.
*/
profile?: KeycloakProfile;
/**
* @private Undocumented.
*/
userInfo?: {}; // KeycloakUserInfo;
/**
* Called when the adapter is initialized.
*/
onReady?(authenticated?: boolean): void;
/**
* Called when a user is successfully authenticated.
*/
onAuthSuccess?(): void;
/**
* Called if there was an error during authentication.
*/
onAuthError?(errorData: KeycloakError): void;
/**
* Called when the token is refreshed.
*/
onAuthRefreshSuccess?(): void;
/**
* Called if there was an error while trying to refresh the token.
*/
onAuthRefreshError?(): void;
/**
* Called if the user is logged out (will only be called if the session
* status iframe is enabled, or in Cordova mode).
*/
onAuthLogout?(): void;
/**
* Called when the access token is expired. If a refresh token is available
* the token can be refreshed with Keycloak#updateToken, or in cases where
* it's not (ie. with implicit flow) you can redirect to login screen to
* obtain a new access token.
*/
onTokenExpired?(): void;
/**
* Called to initialize the adapter.
* @param initOptions Initialization options.
* @returns A promise to set functions to be invoked on success or error.
*/
init(initOptions: KeycloakInitOptions): KeycloakPromise<boolean, KeycloakError>;
/**
* Redirects to login form.
* @param options Login options.
*/
login(options?: KeycloakLoginOptions): KeycloakPromise<void, void>;
/**
* Redirects to logout.
* @param options Logout options.
* @param options.redirectUri Specifies the uri to redirect to after logout.
*/
logout(options?: any): KeycloakPromise<void, void>;
/**
* Redirects to registration form.
* @param options Supports same options as Keycloak#login but `action` is
* set to `'register'`.
*/
register(options?: any): KeycloakPromise<void, void>;
/**
* Redirects to the Account Management Console.
*/
accountManagement(): KeycloakPromise<void, void>;
/**
* Returns the URL to login form.
* @param options Supports same options as Keycloak#login.
*/
createLoginUrl(options?: KeycloakLoginOptions): string;
/**
* Returns the URL to logout the user.
* @param options Logout options.
* @param options.redirectUri Specifies the uri to redirect to after logout.
*/
createLogoutUrl(options?: any): string;
/**
* Returns the URL to registration page.
* @param options Supports same options as Keycloak#createLoginUrl but
* `action` is set to `'register'`.
*/
createRegisterUrl(options?: KeycloakLoginOptions): string;
/**
* Returns the URL to the Account Management Console.
*/
createAccountUrl(): string;
/**
* Returns true if the token has less than `minValidity` seconds left before
* it expires.
* @param minValidity If not specified, `0` is used.
*/
isTokenExpired(minValidity?: number): boolean;
/**
* If the token expires within `minValidity` seconds, the token is refreshed.
* If the session status iframe is enabled, the session status is also
* checked.
* @returns A promise to set functions that can be invoked if the token is
* still valid, or if the token is no longer valid.
* @example
* ```js
* keycloak.updateToken(5).success(function(refreshed) {
* if (refreshed) {
* alert('Token was successfully refreshed');
* } else {
* alert('Token is still valid');
* }
* }).error(function() {
* alert('Failed to refresh the token, or the session has expired');
* });
*/
updateToken(minValidity: number): KeycloakPromise<boolean, boolean>;
/**
* Clears authentication state, including tokens. This can be useful if
* the application has detected the session was expired, for example if
* updating token fails. Invoking this results in Keycloak#onAuthLogout
* callback listener being invoked.
*/
clearToken(): void;
/**
* Returns true if the token has the given realm role.
* @param role A realm role name.
*/
hasRealmRole(role: string): boolean;
/**
* Returns true if the token has the given role for the resource.
* @param role A role name.
* @param resource If not specified, `clientId` is used.
*/
hasResourceRole(role: string, resource?: string): boolean;
/**
* Loads the user's profile.
* @returns A promise to set functions to be invoked on success or error.
*/
loadUserProfile(): KeycloakPromise<KeycloakProfile, void>;
/**
* @private Undocumented.
*/
loadUserInfo(): KeycloakPromise<{}, void>;
}
}
/*
* MIT License
*
* Copyright 2017 Brett Epps <https://github.com/eppsilon>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
export as namespace Keycloak;
export = Keycloak;
/**
* Creates a new Keycloak client instance.
* @param config Path to a JSON config file or a plain config object.
*/
declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance;
declare namespace Keycloak {
type KeycloakAdapterName = 'cordova'|'default' | any;
type KeycloakOnLoad = 'login-required'|'check-sso';
type KeycloakResponseMode = 'query'|'fragment';
type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
type KeycloakFlow = 'standard'|'implicit'|'hybrid';
interface KeycloakInitOptions {
/**
* @private Undocumented.
*/
useNonce?: boolean;
/**
* Allows to use different adapter:
*
* - {string} default - using browser api for redirects
* - {string} cordova - using cordova plugins
* - {function} - allows to provide custom function as adapter.
*/
adapter?: KeycloakAdapterName;
/**
* Specifies an action to do on load.
*/
onLoad?: KeycloakOnLoad;
/**
* Set an initial value for the token.
*/
token?: string;
/**
* Set an initial value for the refresh token.
*/
refreshToken?: string;
/**
* Set an initial value for the id token (only together with `token` or
* `refreshToken`).
*/
idToken?: string;
/**
* Set an initial value for skew between local time and Keycloak server in
* seconds (only together with `token` or `refreshToken`).
*/
timeSkew?: number;
/**
* Set to enable/disable monitoring login state.
* @default true
*/
checkLoginIframe?: boolean;
/**
* Set the interval to check login state (in seconds).
* @default 5
*/
checkLoginIframeInterval?: number;
/**
* Set the OpenID Connect response mode to send to Keycloak upon login.
* @default fragment After successful authentication Keycloak will redirect
* to JavaScript application with OpenID Connect parameters
* added in URL fragment. This is generally safer and
* recommended over query.
*/
responseMode?: KeycloakResponseMode;
/**
* Set the OpenID Connect flow.
* @default standard
*/
flow?: KeycloakFlow;
}
interface KeycloakLoginOptions {
/**
* @private Undocumented.
*/
scope?: string;
/**
* Specifies the uri to redirect to after login.
*/
redirectUri?: string;
/**
* By default the login screen is displayed if the user is not logged into
* Keycloak. To only authenticate to the application if the user is already
* logged in and not display the login page if the user is not logged in, set
* this option to `'none'`. To always require re-authentication and ignore
* SSO, set this option to `'login'`.
*/
prompt?: 'none'|'login';
/**
* If value is `'register'` then user is redirected to registration page,
* otherwise to login page.
*/
action?: 'register';
/**
* Used just if user is already authenticated. Specifies maximum time since
* the authentication of user happened. If user is already authenticated for
* longer time than `'maxAge'`, the SSO is ignored and he will need to
* authenticate again.
*/
maxAge?: number;
/**
* Used to pre-fill the username/email field on the login form.
*/
loginHint?: string;
/**
* Used to tell Keycloak which IDP the user wants to authenticate with.
*/
idpHint?: string;
/**
* Sets the 'ui_locales' query param in compliance with section 3.1.2.1
* of the OIDC 1.0 specification.
*/
locale?: string;
/**
* Specifies the desired Keycloak locale for the UI. This differs from
* the locale param in that it tells the Keycloak server to set a cookie and update
* the user's profile to a new preferred locale.
*/
kcLocale?: string;
}
type KeycloakPromiseCallback<T> = (result: T) => void;
interface KeycloakPromise<TSuccess, TError> {
/**
* Function to call if the promised action succeeds.
*/
success(callback: KeycloakPromiseCallback<TSuccess>): KeycloakPromise<TSuccess, TError>;
/**
* Function to call if the promised action throws an error.
*/
error(callback: KeycloakPromiseCallback<TError>): KeycloakPromise<TSuccess, TError>;
}
interface KeycloakError {
error: string;
error_description: string;
}
interface KeycloakAdapter {
login(options?: KeycloakLoginOptions): KeycloakPromise<void, void>;
logout(options?: any): KeycloakPromise<void, void>;
register(options?: KeycloakLoginOptions): KeycloakPromise<void, void>;
accountManagement(): KeycloakPromise<void, void>;
redirectUri(options: { redirectUri: string; }, encodeHash: boolean): string;
}
interface KeycloakProfile {
id?: string;
username?: string;
email?: string;
firstName?: string;
lastName?: string;
enabled?: boolean;
emailVerified?: boolean;
totp?: boolean;
createdTimestamp?: number;
}
// export interface KeycloakUserInfo {}
/**
* A client for the Keycloak authentication server.
* @see {@link https://keycloak.gitbooks.io/securing-client-applications-guide/content/topics/oidc/javascript-adapter.html|Keycloak JS adapter documentation}
*/
interface KeycloakInstance {
/**
* Is true if the user is authenticated, false otherwise.
*/
authenticated?: boolean;
/**
* The user id.
*/
subject?: string;
/**
* Response mode passed in init (default value is `'fragment'`).
*/
responseMode?: KeycloakResponseMode;
/**
* Response type sent to Keycloak with login requests. This is determined
* based on the flow value used during initialization, but can be overridden
* by setting this value.
*/
responseType?: KeycloakResponseType;
/**
* Flow passed in init.
*/
flow?: KeycloakFlow;
/**
* The realm roles associated with the token.
*/
realmAccess?: { roles: string[] };
/**
* The resource roles associated with the token.
*/
resourceAccess?: string[];
/**
* The base64 encoded token that can be sent in the Authorization header in
* requests to services.
*/
token?: string;
/**
* The parsed token as a JavaScript object.
*/
tokenParsed?: {
exp?: number;
iat?: number;
nonce?: string;
sub?: string;
session_state?: string;
realm_access?: { roles: string[] };
resource_access?: string[];
};
/**
* The base64 encoded refresh token that can be used to retrieve a new token.
*/
refreshToken?: string;
/**
* The parsed refresh token as a JavaScript object.
*/
refreshTokenParsed?: { nonce?: string };
/**
* The base64 encoded ID token.
*/
idToken?: string;
/**
* The parsed id token as a JavaScript object.
*/
idTokenParsed?: { nonce?: string };
/**
* The estimated time difference between the browser time and the Keycloak
* server in seconds. This value is just an estimation, but is accurate
* enough when determining if a token is expired or not.
*/
timeSkew?: number;
/**
* @private Undocumented.
*/
loginRequired?: boolean;
/**
* @private Undocumented.
*/
authServerUrl?: string;
/**
* @private Undocumented.
*/
realm?: string;
/**
* @private Undocumented.
*/
clientId?: string;
/**
* @private Undocumented.
*/
clientSecret?: string;
/**
* @private Undocumented.
*/
redirectUri?: string;
/**
* @private Undocumented.
*/
sessionId?: string;
/**
* @private Undocumented.
*/
profile?: KeycloakProfile;
/**
* @private Undocumented.
*/
userInfo?: {}; // KeycloakUserInfo;
/**
* Called when the adapter is initialized.
*/
onReady?(authenticated?: boolean): void;
/**
* Called when a user is successfully authenticated.
*/
onAuthSuccess?(): void;
/**
* Called if there was an error during authentication.
*/
onAuthError?(errorData: KeycloakError): void;
/**
* Called when the token is refreshed.
*/
onAuthRefreshSuccess?(): void;
/**
* Called if there was an error while trying to refresh the token.
*/
onAuthRefreshError?(): void;
/**
* Called if the user is logged out (will only be called if the session
* status iframe is enabled, or in Cordova mode).
*/
onAuthLogout?(): void;
/**
* Called when the access token is expired. If a refresh token is available
* the token can be refreshed with Keycloak#updateToken, or in cases where
* it's not (ie. with implicit flow) you can redirect to login screen to
* obtain a new access token.
*/
onTokenExpired?(): void;
/**
* Called to initialize the adapter.
* @param initOptions Initialization options.
* @returns A promise to set functions to be invoked on success or error.
*/
init(initOptions: KeycloakInitOptions): KeycloakPromise<boolean, KeycloakError>;
/**
* Redirects to login form.
* @param options Login options.
*/
login(options?: KeycloakLoginOptions): KeycloakPromise<void, void>;
/**
* Redirects to logout.
* @param options Logout options.
* @param options.redirectUri Specifies the uri to redirect to after logout.
*/
logout(options?: any): KeycloakPromise<void, void>;
/**
* Redirects to registration form.
* @param options Supports same options as Keycloak#login but `action` is
* set to `'register'`.
*/
register(options?: any): KeycloakPromise<void, void>;
/**
* Redirects to the Account Management Console.
*/
accountManagement(): KeycloakPromise<void, void>;
/**
* Returns the URL to login form.
* @param options Supports same options as Keycloak#login.
*/
createLoginUrl(options?: KeycloakLoginOptions): string;
/**
* Returns the URL to logout the user.
* @param options Logout options.
* @param options.redirectUri Specifies the uri to redirect to after logout.
*/
createLogoutUrl(options?: any): string;
/**
* Returns the URL to registration page.
* @param options Supports same options as Keycloak#createLoginUrl but
* `action` is set to `'register'`.
*/
createRegisterUrl(options?: KeycloakLoginOptions): string;
/**
* Returns the URL to the Account Management Console.
*/
createAccountUrl(): string;
/**
* Returns true if the token has less than `minValidity` seconds left before
* it expires.
* @param minValidity If not specified, `0` is used.
*/
isTokenExpired(minValidity?: number): boolean;
/**
* If the token expires within `minValidity` seconds, the token is refreshed.
* If the session status iframe is enabled, the session status is also
* checked.
* @returns A promise to set functions that can be invoked if the token is
* still valid, or if the token is no longer valid.
* @example
* ```js
* keycloak.updateToken(5).success(function(refreshed) {
* if (refreshed) {
* alert('Token was successfully refreshed');
* } else {
* alert('Token is still valid');
* }
* }).error(function() {
* alert('Failed to refresh the token, or the session has expired');
* });
*/
updateToken(minValidity: number): KeycloakPromise<boolean, boolean>;
/**
* Clears authentication state, including tokens. This can be useful if
* the application has detected the session was expired, for example if
* updating token fails. Invoking this results in Keycloak#onAuthLogout
* callback listener being invoked.
*/
clearToken(): void;
/**
* Returns true if the token has the given realm role.
* @param role A realm role name.
*/
hasRealmRole(role: string): boolean;
/**
* Returns true if the token has the given role for the resource.
* @param role A role name.
* @param resource If not specified, `clientId` is used.
*/
hasResourceRole(role: string, resource?: string): boolean;
/**
* Loads the user's profile.
* @returns A promise to set functions to be invoked on success or error.
*/
loadUserProfile(): KeycloakPromise<KeycloakProfile, void>;
/**
* @private Undocumented.
*/
loadUserInfo(): KeycloakPromise<{}, void>;
}
}

View file

@ -89,9 +89,7 @@ public class AccountConsole {
map.put("authUrl", session.getContext().getContextPath());
map.put("baseUrl", session.getContext().getContextPath() + "/realms/" + realm.getName() + "/account");
map.put("realm", realm.getName());
map.put("isRegistrationEmailAsUsername", realm.isRegistrationEmailAsUsername());
map.put("isEditUserNameAllowed", realm.isEditUsernameAllowed());
map.put("realm", realm);
map.put("resourceUrl", Urls.themeRoot(baseUri).getPath() + "/account/" + theme.getName());
map.put("resourceVersion", Version.RESOURCES_VERSION);
@ -108,7 +106,7 @@ public class AccountConsole {
Properties messages = theme.getMessages(locale);
map.put("msg", new MessageFormatterMethod(locale, messages));
map.put("msgJSON", messagesToJsonString(messages));
map.put("supportedLocales", supportedLocales(messages));
map.put("properties", theme.getProperties());
FreeMarkerUtil freeMarkerUtil = new FreeMarkerUtil();
@ -118,7 +116,16 @@ public class AccountConsole {
return builder.build();
}
}
private Map<String, String> supportedLocales(Properties messages) throws IOException {
Map<String, String> supportedLocales = new HashMap<>();
for (String l : realm.getSupportedLocales()) {
String label = messages.getProperty("locale_" + l, l);
supportedLocales.put(l, label);
}
return supportedLocales;
}
private String messagesToJsonString(Properties props) {
if (props == null) return "";

View file

@ -4,6 +4,7 @@ doLogOutAllSessions=Log out all sessions
doRemove=Remove
doAdd=Add
doSignOut=Sign Out
doLogIn=Log In
editAccountHtmlTitle=Edit Account
personalInfoHtmlTitle=Personal Info
@ -210,18 +211,18 @@ permissionRequestion=Permission Requestion
permission=Permission
shares=share(s)
locale_ca=Catal\u00E0
locale_ca=Catal\u00e0
locale_de=Deutsch
locale_en=English
locale_es=Espa\u00F1ol
locale_es=Espa\u00f1ol
locale_fr=Fran\u00e7ais
locale_it=Italian
locale_ja=\u65E5\u672C\u8A9E
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_sk=Sloven\u010Dina
locale_pt-BR=Portugu\u00eas (Brasil)
locale_ru=\u0420\u0443\u0441\u0441\u043a\u0438\u0439
locale_sk=Sloven\u010dina
locale_sv=Svenska
locale_zh-CN=\u4e2d\u6587\u7b80\u4f53

View file

@ -6,10 +6,16 @@
<script>
var authUrl = '${authUrl}';
var baseUrl = '${baseUrl}';
var realm = '${realm}';
var realm = '${realm.name}';
var resourceUrl = '${resourceUrl}';
var isRegistrationEmailAsUsername = ${isRegistrationEmailAsUsername?c};
var isEditUserNameAllowed = ${isEditUserNameAllowed?c};
var isRegistrationEmailAsUsername = ${realm.registrationEmailAsUsername?c};
var isEditUserNameAllowed = ${realm.editUsernameAllowed?c};
var isInternationalizationEnabled = ${realm.internationalizationEnabled?c};
var availableLocales = [];
<#list supportedLocales as locale, label>
availableLocales.push({locale : '${locale}', label : '${label}'});
</#list>
<#if referrer??>
var referrer = '${referrer}';
@ -67,7 +73,7 @@
<script src="${authUrl}/js/keycloak.js"></script>
<script>
var keycloak = Keycloak('${authUrl}/realms/${realm}/account/keycloak.json');
var keycloak = Keycloak('${authUrl}/realms/${realm.name}/account/keycloak.json');
keycloak.init({onLoad: 'check-sso'}).success(function(authenticated) {
var loadjs = function (url,loadListener) {
const script = document.createElement("script");
@ -128,27 +134,15 @@
we are unable to localize the button's message. Not sure what to do about that yet.
-->
<ul class="nav navbar-nav navbar-right navbar-iconic">
<li><button id="signInButton" style="visibility:hidden" onclick="keycloak.login();" class="btn btn-primary btn-lg btn-sign" type="button">Log In</button></li>
<li><button id="signInButton" style="visibility:hidden" onclick="keycloak.login();" class="btn btn-primary btn-lg btn-sign" type="button">${msg("doLogIn")}</button></li>
<li class="dropdown">
<a href="#0" class="dropdown-toggle nav-item-iconic" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
${msg("locale_en")} <span class="caret"></span>
${msg("locale_" + locale)} <span class="caret"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a href="#">${msg("locale_ca")}</a></li>
<li><a href="#">${msg("locale_de")}</a></li>
<li><a href="#">${msg("locale_en")}</a></li>
<li><a href="#">${msg("locale_es")}</a></li>
<li><a href="#">${msg("locale_fr")}</a></li>
<li><a href="#">${msg("locale_it")}</a></li>
<li><a href="#">${msg("locale_ja")}</a></li>
<li><a href="#">${msg("locale_nl")}</a></li>
<li><a href="#">${msg("locale_no")}</a></li>
<li><a href="#">${msg("locale_lt")}</a></li>
<li><a href="#">${msg("locale_pt-BR")}</a></li>
<li><a href="#">${msg("locale_ru")}</a></li>
<li><a href="#">${msg("locale_sk")}</a></li>
<li><a href="#">${msg("locale_sv")}</a></li>
<li><a href="#">${msg("locale_zh-CN")}</a></li>
<#list supportedLocales as locale, label>
<li><a href="${baseUrl}/?kc_locale=${locale}">${label}</a></li>
</#list>
</ul>
</li>
</ul>

View file

@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright 2017 Andy Hanson
* Copyright 2017 Brett Epps <https://github.com/eppsilon>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including
@ -29,7 +29,7 @@ export = Keycloak;
declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance;
declare namespace Keycloak {
type KeycloakAdapterName = 'cordova'|'default';
type KeycloakAdapterName = 'cordova'|'default' | any;
type KeycloakOnLoad = 'login-required'|'check-sso';
type KeycloakResponseMode = 'query'|'fragment';
type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
@ -39,8 +39,17 @@ declare namespace Keycloak {
/**
* @private Undocumented.
*/
adapter?: KeycloakAdapterName;
useNonce?: boolean;
/**
* Allows to use different adapter:
*
* - {string} default - using browser api for redirects
* - {string} cordova - using cordova plugins
* - {function} - allows to provide custom function as adapter.
*/
adapter?: KeycloakAdapterName;
/**
* Specifies an action to do on load.
*/
@ -78,7 +87,7 @@ declare namespace Keycloak {
* Set the interval to check login state (in seconds).
* @default 5
*/
checkLoginIframeInterval?: boolean;
checkLoginIframeInterval?: number;
/**
* Set the OpenID Connect response mode to send to Keycloak upon login.
@ -140,10 +149,18 @@ declare namespace Keycloak {
*/
idpHint?: string;
/**
* Specifies the desired locale for the UI.
/**
* Sets the 'ui_locales' query param in compliance with section 3.1.2.1
* of the OIDC 1.0 specification.
*/
locale?: string;
/**
* Specifies the desired Keycloak locale for the UI. This differs from
* the locale param in that it tells the Keycloak server to set a cookie and update
* the user's profile to a new preferred locale.
*/
kcLocale?: string;
}
type KeycloakPromiseCallback<T> = (result: T) => void;

View file

@ -51,6 +51,8 @@
adapter = loadAdapter('cordova');
} else if (initOptions && initOptions.adapter === 'default') {
adapter = loadAdapter();
} else if (initOptions && typeof initOptions.adapter === "object") {
adapter = initOptions.adapter;
} else {
if (window.Cordova || window.cordova) {
adapter = loadAdapter('cordova');
@ -280,6 +282,10 @@
if (options && options.locale) {
url += '&ui_locales=' + encodeURIComponent(options.locale);
}
if (options && options.kcLocale) {
url += '&kc_locale=' + encodeURIComponent(options.kcLocale);
}
return url;
}
@ -464,6 +470,10 @@
} else {
console.warn('[KEYCLOAK] Failed to refresh token');
if (req.status == 400) {
kc.clearToken();
}
kc.onAuthRefreshError && kc.onAuthRefreshError();
for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {
p.setError(true);

View file

@ -28,6 +28,12 @@
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
<li><a href="#" (click)="logout()">{{'doSignOut' | translate}}</a></li>
<li class="dropdown-submenu pull-left">
<a class="test" tabindex="-1" href="#">Change language</a>
<ul class="dropdown-menu">
<li *ngFor="let locale of availableLocales" (click)="changeLocale(locale.locale)"><a tabindex="-1" href="#">{{ locale.label }}</a></li>
</ul>
</li>
</ul>
</li>
</ul>

View file

@ -24,6 +24,7 @@ declare const resourceUrl: string;
declare const baseUrl: string;
declare const referrer: string;
declare const referrer_uri: string;
declare const availableLocales: Array<Object>;
@Component({
selector: 'app-top-nav',
@ -34,10 +35,13 @@ export class TopNavComponent implements OnInit {
@Input() showSideNav: String;
public resourceUrl: string = resourceUrl;
public availableLocales: Array<Object> = availableLocales;
private referrer: Referrer;
constructor(private keycloakService: KeycloakService, translateUtil: TranslateUtil, private respSvc: ResponsivenessService) {
constructor(private keycloakService: KeycloakService,
translateUtil: TranslateUtil,
private respSvc: ResponsivenessService) {
this.referrer = new Referrer(translateUtil);
}
@ -51,5 +55,9 @@ export class TopNavComponent implements OnInit {
private logout() {
this.keycloakService.logout(baseUrl);
}
private changeLocale(newLocale: string) {
this.keycloakService.login({kcLocale: newLocale });
}
}