Updates to keycloak.js, including adding support for Cordova
Conflicts: examples/cordova/example-realm.json examples/js-console/src/main/webapp/index.html integration/js/src/main/resources/META-INF/resources/js/keycloak.js
This commit is contained in:
parent
2d5e6520db
commit
b5bdeae2a2
12 changed files with 484 additions and 125 deletions
4
examples/cordova/.gitignore
vendored
Normal file
4
examples/cordova/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
platforms
|
||||
plugins
|
||||
www/keycloak.js
|
||||
www/keycloak.json
|
31
examples/cordova/README.md
Normal file
31
examples/cordova/README.md
Normal file
|
@ -0,0 +1,31 @@
|
|||
Basic Cordova Example
|
||||
=====================
|
||||
|
||||
Before running this example you need to have Cordova installed with a phone or emulator available.
|
||||
|
||||
Start and configure Keycloak
|
||||
----------------------------
|
||||
|
||||
Start Keycloak bound to an IP address available to the phone or emulator. For example:
|
||||
|
||||
bin/standalone.sh -b 192.168.0.10
|
||||
|
||||
Open the Keycloak admin console, click on Add Realm, click on 'Choose a JSON file', selct example-realm.json and click Upload.
|
||||
|
||||
Navigate to applications, click on 'Cordova', select 'Installation' and in the 'Format option' drop-down select 'keycloak.json'. Download this file to the www folder.
|
||||
|
||||
Download '/js/keycloak.js' from the server to the www folder as well. For example:
|
||||
|
||||
wget http://192.168.0.10:8080/auth/js/keycloak.js
|
||||
|
||||
|
||||
Install to Android phone or emulator
|
||||
------------------------------------
|
||||
|
||||
mkdir platforms plugins
|
||||
cordova plugin add org.apache.cordova.inappbrowser
|
||||
cordova platform add android
|
||||
cordova run android
|
||||
|
||||
|
||||
Once the application is opened you can login with username: 'user', and password: 'password'.
|
72
examples/cordova/example-realm.json
Executable file
72
examples/cordova/example-realm.json
Executable file
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"realm": "example",
|
||||
"enabled": true,
|
||||
"sslNotRequired": true,
|
||||
"registrationAllowed": true,
|
||||
"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" : "user",
|
||||
"enabled": true,
|
||||
"email" : "sample-user@example",
|
||||
"firstName": "Sample",
|
||||
"lastName": "User",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"roles" : {
|
||||
"realm" : [
|
||||
{
|
||||
"name": "user",
|
||||
"description": "User privileges"
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"description": "Administrator privileges"
|
||||
}
|
||||
]
|
||||
},
|
||||
"roleMappings": [
|
||||
{
|
||||
"username": "user",
|
||||
"roles": ["user"]
|
||||
}
|
||||
],
|
||||
"scopeMappings": [
|
||||
{
|
||||
"client": "cordova",
|
||||
"roles": ["user"]
|
||||
}
|
||||
],
|
||||
"applications": [
|
||||
{
|
||||
"name": "cordova",
|
||||
"enabled": true,
|
||||
"publicClient": true,
|
||||
"redirectUris": [
|
||||
"http://localhost"
|
||||
]
|
||||
}
|
||||
],
|
||||
"applicationRoleMappings": {
|
||||
"account": [
|
||||
{
|
||||
"username": "user",
|
||||
"roles": ["view-profile", "manage-account"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"applicationScopeMappings": {
|
||||
"account": [
|
||||
{
|
||||
"client": "cordova",
|
||||
"roles": ["view-profile"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
14
examples/cordova/www/config.xml
Normal file
14
examples/cordova/www/config.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0" id="org.keycloak.examples.cordova" version="1.0.0">
|
||||
<name>Keycloak Auth</name>
|
||||
<description>Keycloak Cordova Example</description>
|
||||
<author href="http://www.keycloak.org">Keycloak Team</author>
|
||||
|
||||
<feature name="http://api.phonegap.com/1.0/device" />
|
||||
|
||||
<preference name="permissions" value="none"/>
|
||||
|
||||
<gap:plugin name="org.apache.cordova.inappbrowser" />
|
||||
|
||||
<access origin="http://*"/>
|
||||
</widget>
|
77
examples/cordova/www/index.html
Normal file
77
examples/cordova/www/index.html
Normal file
|
@ -0,0 +1,77 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Authentication Example</title>
|
||||
|
||||
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="keycloak.js"></script>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
var keycloak = new Keycloak();
|
||||
|
||||
keycloak.onReady = updateState;
|
||||
keycloak.onAuthSuccess = updateState;
|
||||
keycloak.onAuthRefreshSuccess = updateState;
|
||||
keycloak.onAuthLogout = updateState;
|
||||
|
||||
function updateState() {
|
||||
console.debug('Updating state');
|
||||
|
||||
if (keycloak.authenticated) {
|
||||
document.getElementById('authenticated').style.display = 'block';
|
||||
document.getElementById('not-authenticated').style.display = 'none';
|
||||
|
||||
document.getElementById('subject').innerText = keycloak.subject;
|
||||
document.getElementById('username').innerText = keycloak.idToken.preferred_username;
|
||||
document.getElementById('tokenExpires').innerText = new Date(keycloak.tokenParsed.exp * 1000).toLocaleString();
|
||||
document.getElementById('tokenRefreshExpires').innerText = new Date(keycloak.refreshTokenParsed.exp * 1000).toLocaleString();
|
||||
} else {
|
||||
document.getElementById('authenticated').style.display = 'none';
|
||||
document.getElementById('not-authenticated').style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("deviceready", function() {
|
||||
console.debug('Device ready');
|
||||
|
||||
keycloak.init('check-sso');
|
||||
}, false);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="authenticated" style="display: none;">
|
||||
<div>
|
||||
<button onclick="keycloak.logout()">Log out</button>
|
||||
<button onclick="keycloak.updateToken()">Refresh token</button>
|
||||
</div>
|
||||
<div>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Subject</td>
|
||||
<td id="subject"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td id="username"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Token expires</td>
|
||||
<td id="tokenExpires"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Refresh token expires</td>
|
||||
<td id="tokenRefreshExpires"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="not-authenticated" style="display: none;">
|
||||
<div>
|
||||
<button onclick="keycloak.login()">Log in</button>
|
||||
</div>
|
||||
<div>
|
||||
<p>Not authenticated</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -14,14 +14,6 @@
|
|||
<name>Customer Portal CLI</name>
|
||||
<description/>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jboss</id>
|
||||
<name>jboss repo</name>
|
||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
|
@ -32,6 +24,14 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jboss.as.plugins</groupId>
|
||||
<artifactId>jboss-as-maven-plugin</artifactId>
|
||||
<version>7.4.Final</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
</head>
|
||||
<body bgcolor="#E3F6CE">
|
||||
|
||||
<p>Goto: <a href="#" onclick="keycloak.logout()">logout</a></p>
|
||||
<p>Goto: <a href="http://localhost:8080/product-portal">products</a> | <a href="#" onclick="keycloak.logout()">logout</a> | <a href="#" onclick="keycloak.accountManagement()">manage acct</a></p>
|
||||
|
||||
User <b id="subject"></b> made this request.
|
||||
<p><b>User details (from <span id="profileType"></span>)</b></p>
|
||||
<p>Username: <span id="username"></span></p>
|
||||
|
@ -18,16 +19,11 @@ User <b id="subject"></b> made this request.
|
|||
<div id="customers"></div>
|
||||
|
||||
<script>
|
||||
var keycloak = Keycloak({
|
||||
clientId: 'customer-portal-js',
|
||||
realm: 'demo',
|
||||
onload: 'login-required'
|
||||
});
|
||||
var keycloak = Keycloak('../keycloak.json');
|
||||
|
||||
var loadData = function () {
|
||||
document.getElementById('subject').innerText = keycloak.subject;
|
||||
|
||||
console.debug(keycloak.idToken);
|
||||
if (keycloak.idToken) {
|
||||
document.getElementById('profileType').innerText = 'IDToken';
|
||||
document.getElementById('username').innerText = keycloak.idToken.preferred_username;
|
||||
|
@ -74,14 +70,14 @@ User <b id="subject"></b> made this request.
|
|||
|
||||
var loadFailure = function () {
|
||||
document.getElementById('customers').innerHTML = '<b>Failed to load data. Check console log</b>';
|
||||
|
||||
};
|
||||
|
||||
var reloadData = function () {
|
||||
keycloak.onValidAccessToken(loadData, loadFailure);
|
||||
keycloak.updateToken(10).success(loadData).error(loadFailure);
|
||||
}
|
||||
|
||||
keycloak.init(loadData, loadFailure);
|
||||
keycloak.onAuthSuccess = loadData;
|
||||
keycloak.init('login-required');
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"auth-server-url" : "http://localhost:8080/auth",
|
||||
"ssl-not-required" : true,
|
||||
"resource" : "customer-portal-js",
|
||||
"public-client" : true
|
||||
}
|
|
@ -51,6 +51,10 @@
|
|||
"client": "customer-portal",
|
||||
"roles": ["user"]
|
||||
},
|
||||
{
|
||||
"client": "customer-portal-js",
|
||||
"roles": ["user"]
|
||||
},
|
||||
{
|
||||
"client": "product-portal",
|
||||
"roles": ["user"]
|
||||
|
|
17
examples/js-console/README.md
Normal file
17
examples/js-console/README.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
Basic JavaScript Example
|
||||
========================
|
||||
|
||||
Start and configure Keycloak
|
||||
----------------------------
|
||||
|
||||
Start Keycloak:
|
||||
|
||||
bin/standalone.sh
|
||||
|
||||
Open the Keycloak admin console, click on Add Realm, click on 'Choose a JSON file', selct example-realm.json and click Upload.
|
||||
|
||||
Deploy the JS Console to Keycloak by running:
|
||||
|
||||
mvn install jboss-as:deploy
|
||||
|
||||
Open the console at http://localhost:8080/js-console and login with username: 'user', and password: 'password'.
|
|
@ -1,6 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="http://localhost:8080/auth/js/keycloak.js"></script>
|
||||
<script src="/auth/js/keycloak.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
|||
}
|
||||
|
||||
function refreshToken(minValidity) {
|
||||
keycloak.refreshAccessToken(minValidity).success(function(refreshed) {
|
||||
keycloak.updateToken(minValidity).success(function(refreshed) {
|
||||
if (refreshed) {
|
||||
output(keycloak.tokenParsed);
|
||||
} else {
|
||||
|
|
|
@ -4,107 +4,117 @@ var Keycloak = function (config) {
|
|||
}
|
||||
|
||||
var kc = this;
|
||||
kc.authenticated = false;
|
||||
|
||||
var configPromise = createPromise();
|
||||
configPromise.name = 'config';
|
||||
|
||||
if (!config) {
|
||||
loadConfig('keycloak.json', configPromise);
|
||||
} else if (typeof config === 'string') {
|
||||
loadConfig(config, configPromise);
|
||||
} else {
|
||||
if (!config['url']) {
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.match(/.*keycloak\.js/)) {
|
||||
config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.realm) {
|
||||
throw 'realm missing';
|
||||
}
|
||||
|
||||
if (!config.clientId) {
|
||||
throw 'clientId missing';
|
||||
}
|
||||
|
||||
kc.authServerUrl = config.url;
|
||||
kc.realm = config.realm;
|
||||
kc.clientId = config.clientId;
|
||||
|
||||
configPromise.setSuccess();
|
||||
}
|
||||
var adapter;
|
||||
|
||||
kc.init = function (init) {
|
||||
kc.authenticated = false;
|
||||
|
||||
if (window.Cordova) {
|
||||
adapter = loadAdapter('cordova');
|
||||
} else {
|
||||
adapter = loadAdapter();
|
||||
}
|
||||
|
||||
var promise = createPromise();
|
||||
var callback = parseCallback(window.location.href);
|
||||
|
||||
var initPromise = createPromise();
|
||||
initPromise.promise.success(function() {
|
||||
kc.onReady && kc.onReady(kc.authenticated);
|
||||
promise.setSuccess(kc.authenticated);
|
||||
}).error(promise.error);
|
||||
|
||||
var configPromise = loadConfig(config);
|
||||
|
||||
function processInit() {
|
||||
var callback = parseCallback(window.location.href);
|
||||
if (callback) {
|
||||
window.history.replaceState({}, null, location.protocol + '//' + location.host + location.pathname + (callback.fragment ? '#' + callback.fragment : ''));
|
||||
processCallback(callback, promise);
|
||||
processCallback(callback, initPromise);
|
||||
return;
|
||||
} else if (init) {
|
||||
if (init.code || init.error) {
|
||||
processCallback(init, promise);
|
||||
processCallback(init, initPromise);
|
||||
return;
|
||||
} else if (init.token || init.refreshToken) {
|
||||
setToken(init.token, init.refreshToken);
|
||||
initPromise.setSuccess();
|
||||
} else if (init == 'login-required') {
|
||||
kc.login();
|
||||
return;
|
||||
var p = kc.login();
|
||||
if (p) {
|
||||
p.success(function() {
|
||||
initPromise.setSuccess();
|
||||
}).error(function() {
|
||||
initPromise.setError();
|
||||
});
|
||||
};
|
||||
} else if (init == 'check-sso') {
|
||||
window.location = kc.createLoginUrl() + '&prompt=none';
|
||||
return;
|
||||
var p = kc.login({ prompt: 'none' });
|
||||
if (p) {
|
||||
p.success(function() {
|
||||
initPromise.setSuccess();
|
||||
}).error(function() {
|
||||
initPromise.setSuccess();
|
||||
});
|
||||
};
|
||||
} else {
|
||||
throw 'invalid init: ' + init;
|
||||
}
|
||||
} else {
|
||||
initPromise.setSuccess();
|
||||
}
|
||||
|
||||
promise.setSuccess(false);
|
||||
}
|
||||
|
||||
configPromise.promise.success(processInit);
|
||||
configPromise.success(processInit);
|
||||
|
||||
return promise.promise;
|
||||
}
|
||||
|
||||
kc.login = function (redirectUri) {
|
||||
window.location.href = kc.createLoginUrl(redirectUri);
|
||||
kc.login = function (options) {
|
||||
return adapter.login(options);
|
||||
}
|
||||
|
||||
kc.createLoginUrl = function(redirectUri) {
|
||||
kc.createLoginUrl = function(options) {
|
||||
var state = createUUID();
|
||||
|
||||
sessionStorage.oauthState = state;
|
||||
var url = getRealmUrl()
|
||||
+ '/tokens/login'
|
||||
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
||||
+ '&redirect_uri=' + getEncodedRedirectUri(redirectUri)
|
||||
+ '&redirect_uri=' + encodeURIComponent(adapter.redirectUri(options))
|
||||
+ '&state=' + encodeURIComponent(state)
|
||||
+ '&response_type=code';
|
||||
|
||||
if (options && options.prompt) {
|
||||
url += '&prompt=' + options.prompt;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
kc.logout = function(redirectUri) {
|
||||
setToken(null, null);
|
||||
window.location.href = kc.createLogoutUrl(redirectUri);
|
||||
kc.logout = function(options) {
|
||||
return adapter.logout(options);
|
||||
}
|
||||
|
||||
kc.clearToken = function() {
|
||||
setToken(null, null);
|
||||
}
|
||||
|
||||
kc.createLogoutUrl = function(redirectUri) {
|
||||
kc.createLogoutUrl = function(options) {
|
||||
var url = getRealmUrl()
|
||||
+ '/tokens/logout'
|
||||
+ '?redirect_uri=' + getEncodedRedirectUri(redirectUri);
|
||||
+ '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options));
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
kc.createAccountUrl = function() {
|
||||
var url = getRealmUrl()
|
||||
+ '/account'
|
||||
+ '?referrer=' + kc.clientId;
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
kc.accountManagement = function() {
|
||||
return adapter.accountManagement();
|
||||
}
|
||||
|
||||
kc.hasRealmRole = function (role) {
|
||||
var access = kc.realmAccess;
|
||||
return access && access.roles.indexOf(role) >= 0 || false;
|
||||
|
@ -144,7 +154,20 @@ var Keycloak = function (config) {
|
|||
return promise.promise;
|
||||
}
|
||||
|
||||
kc.refreshAccessToken = function(minValidity) {
|
||||
kc.isTokenExpired = function(minValidity) {
|
||||
if (!kc.tokenParsed || !kc.refreshToken) {
|
||||
throw 'Not authenticated';
|
||||
}
|
||||
|
||||
var expiresIn = kc.tokenParsed['exp'] - (new Date().getTime() / 1000);
|
||||
if (minValidity) {
|
||||
expiresIn -= minValidity;
|
||||
}
|
||||
|
||||
return expiresIn < 0;
|
||||
}
|
||||
|
||||
kc.updateToken = function(minValidity) {
|
||||
if (!kc.tokenParsed || !kc.refreshToken) {
|
||||
throw 'Not authenticated';
|
||||
}
|
||||
|
@ -152,8 +175,7 @@ var Keycloak = function (config) {
|
|||
var promise = createPromise();
|
||||
|
||||
if (minValidity) {
|
||||
var expiresIn = kc.tokenParsed['exp'] - (new Date().getTime() / 1000);
|
||||
if (expiresIn > minValidity) {
|
||||
if (!kc.isTokenExpired(minValidity)) {
|
||||
promise.setSuccess(false);
|
||||
return promise.promise;
|
||||
}
|
||||
|
@ -191,15 +213,6 @@ var Keycloak = function (config) {
|
|||
return promise.promise;
|
||||
}
|
||||
|
||||
kc.processCallback = function(url) {
|
||||
var callback = parseCallback(url);
|
||||
if (callback) {
|
||||
var promise = createPromise();
|
||||
processCallback(callback, promise);
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
function getRealmUrl() {
|
||||
return kc.authServerUrl + '/rest/realms/' + encodeURIComponent(kc.realm);
|
||||
}
|
||||
|
@ -231,10 +244,10 @@ var Keycloak = function (config) {
|
|||
var tokenResponse = JSON.parse(req.responseText);
|
||||
setToken(tokenResponse['access_token'], tokenResponse['refresh_token']);
|
||||
kc.onAuthSuccess && kc.onAuthSuccess();
|
||||
promise.setSuccess(true);
|
||||
promise && promise.setSuccess();
|
||||
} else {
|
||||
kc.onAuthError && kc.onAuthError();
|
||||
promise.setError();
|
||||
promise && promise.setError();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -243,33 +256,75 @@ var Keycloak = function (config) {
|
|||
} else if (error) {
|
||||
if (prompt != 'none') {
|
||||
kc.onAuthError && kc.onAuthError();
|
||||
promise.setError();
|
||||
promise && promise.setError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadConfig(url, configPromise) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', url, true);
|
||||
req.setRequestHeader('Accept', 'application/json');
|
||||
function loadConfig(url) {
|
||||
var promise = createPromise();
|
||||
var configUrl;
|
||||
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState == 4) {
|
||||
if (req.status == 200) {
|
||||
var config = JSON.parse(req.responseText);
|
||||
if (!config) {
|
||||
configUrl = 'keycloak.json';
|
||||
} else if (typeof config === 'string') {
|
||||
configUrl = config;
|
||||
}
|
||||
|
||||
kc.authServerUrl = config['auth-server-url'];
|
||||
kc.realm = config['realm'];
|
||||
kc.clientId = config['resource'];
|
||||
if (configUrl) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', configUrl, true);
|
||||
req.setRequestHeader('Accept', 'application/json');
|
||||
|
||||
configPromise.setSuccess();
|
||||
} else {
|
||||
configPromise.setError();
|
||||
req.onreadystatechange = function () {
|
||||
if (req.readyState == 4) {
|
||||
if (req.status == 200) {
|
||||
var config = JSON.parse(req.responseText);
|
||||
|
||||
kc.authServerUrl = config['auth-server-url'];
|
||||
kc.realm = config['realm'];
|
||||
kc.clientId = config['resource'];
|
||||
|
||||
promise.setSuccess();
|
||||
} else {
|
||||
promise.setError();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
req.send();
|
||||
} else {
|
||||
if (!config['url']) {
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.match(/.*keycloak\.js/)) {
|
||||
config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
req.send();
|
||||
if (!config.realm) {
|
||||
throw 'realm missing';
|
||||
}
|
||||
|
||||
if (!config.clientId) {
|
||||
throw 'clientId missing';
|
||||
}
|
||||
|
||||
kc.authServerUrl = config.url;
|
||||
kc.realm = config.realm;
|
||||
kc.clientId = config.clientId;
|
||||
|
||||
promise.setSuccess();
|
||||
}
|
||||
|
||||
return promise.promise;
|
||||
}
|
||||
|
||||
function clearToken() {
|
||||
setToken(null, null);
|
||||
kc.onAuthLogout && kc.onAuthLogout();
|
||||
}
|
||||
|
||||
function setToken(token, refreshToken) {
|
||||
|
@ -310,21 +365,6 @@ var Keycloak = function (config) {
|
|||
}
|
||||
}
|
||||
|
||||
function getEncodedRedirectUri(redirectUri) {
|
||||
var url;
|
||||
if (redirectUri) {
|
||||
url = redirectUri;
|
||||
} else if (kc.redirectUri) {
|
||||
url = kc.redirectUri;
|
||||
} else {
|
||||
url = (location.protocol + '//' + location.hostname + (location.port && (':' + location.port)) + location.pathname);
|
||||
if (location.hash) {
|
||||
url += '?redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
|
||||
}
|
||||
}
|
||||
return encodeURI(url);
|
||||
}
|
||||
|
||||
function createUUID() {
|
||||
var s = [];
|
||||
var hexDigits = '0123456789abcdef';
|
||||
|
@ -339,7 +379,6 @@ var Keycloak = function (config) {
|
|||
}
|
||||
|
||||
function parseCallback(url) {
|
||||
|
||||
if (url.indexOf('?') != -1) {
|
||||
var oauth = {};
|
||||
|
||||
|
@ -365,7 +404,7 @@ var Keycloak = function (config) {
|
|||
}
|
||||
}
|
||||
|
||||
if (oauth.state && oauth.state == sessionStorage.oauthState) {
|
||||
if ((oauth.code || oauth.error) && oauth.state && oauth.state == sessionStorage.oauthState) {
|
||||
delete sessionStorage.oauthState;
|
||||
return oauth;
|
||||
}
|
||||
|
@ -412,6 +451,103 @@ var Keycloak = function (config) {
|
|||
return p;
|
||||
}
|
||||
|
||||
function loadAdapter(type) {
|
||||
if (!type || type == 'default') {
|
||||
return {
|
||||
login: function(options) {
|
||||
window.location.href = kc.createLoginUrl(options);
|
||||
},
|
||||
|
||||
logout: function(options) {
|
||||
window.location.href = kc.createLogoutUrl(options);
|
||||
},
|
||||
|
||||
accountManagement : function() {
|
||||
window.location.href = kc.createAccountUrl();
|
||||
},
|
||||
|
||||
redirectUri: function(options) {
|
||||
if (options && options.redirectUri) {
|
||||
return options.redirectUri;
|
||||
} else if (kc.redirectUri) {
|
||||
return kc.redirectUri;
|
||||
} else {
|
||||
var url = (location.protocol + '//' + location.hostname + (location.port && (':' + location.port)) + location.pathname);
|
||||
if (location.hash) {
|
||||
url += '?redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (type == 'cordova') {
|
||||
console.debug('Enabling Cordova support');
|
||||
|
||||
return {
|
||||
login: function(options) {
|
||||
var promise = createPromise();
|
||||
|
||||
var o = 'location=no';
|
||||
if (options && options.prompt == 'none') {
|
||||
o += ',hidden=yes';
|
||||
}
|
||||
|
||||
var loginUrl = kc.createLoginUrl(options);
|
||||
var ref = window.open(loginUrl, '_blank', o);
|
||||
ref.addEventListener('loadstart', function(event) {
|
||||
if (event.url.indexOf('http://localhost') == 0) {
|
||||
var callback = parseCallback(event.url);
|
||||
ref.close();
|
||||
processCallback(callback);
|
||||
|
||||
if (callback.code) {
|
||||
promise.setSuccess();
|
||||
} else {
|
||||
promise.setError();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return promise.promise;
|
||||
},
|
||||
|
||||
logout: function(options) {
|
||||
var promise = createPromise();
|
||||
|
||||
var logoutUrl = kc.createLogoutUrl(options);
|
||||
var ref = window.open(logoutUrl, '_blank', 'location=no,hidden=yes');
|
||||
ref.addEventListener('loadstart', function(event) {
|
||||
if (event.url.indexOf('http://localhost') == 0) {
|
||||
ref.close();
|
||||
clearToken();
|
||||
promise.setSuccess();
|
||||
}
|
||||
});
|
||||
|
||||
return promise.promise;
|
||||
},
|
||||
|
||||
accountManagement : function() {
|
||||
var accountUrl = kc.createAccountUrl();
|
||||
var ref = window.open(accountUrl, '_blank', 'location=no');
|
||||
ref.addEventListener('loadstart', function(event) {
|
||||
if (event.url.indexOf('http://localhost') == 0) {
|
||||
ref.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
redirectUri: function(options) {
|
||||
return 'http://localhost';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw 'invalid adapter type: ' + type;
|
||||
}
|
||||
|
||||
var idTokenProperties = [
|
||||
"name",
|
||||
"given_name",
|
||||
|
|
Loading…
Reference in a new issue