From 3417b569c08dddb40af19f68d731a58639df98d2 Mon Sep 17 00:00:00 2001 From: Gregor Tudan Date: Sat, 9 Jun 2018 23:26:16 +0200 Subject: [PATCH] KEYCLOAK-2606: add support for native browsers on cordova KEYCLOAK-2606 Added cordova native KEYCLOAK-2606 Some more fixes and tweaks Fix redirect in example realm feature(cordova-native): fix universalLinks and kc options Added 'cordova-native' to typings Added an option to define a "default" redirectUri in keycloak.js Added 'login' and 'logout' event to universalLinks configuration in config.xml Improved 'cordova-native' example to always use a redirectUri and update state after successfull logout Setting the 'authenticated' flag for the keycloak instance to 'false' after a logout redirect KEYCLOAK-2606: Simplify example for cordova-native I wanted to make it explicit which options are actually needed, so I didn't want to reuse the keycloak conf KEYCLOAK-2606: simplify example The update state after logout shouldn't be necessary as it is set in `keycloak.onAuthLogout = updateState;` Not sure why it is called after the login promise... Fixes --- .../oidc/js/src/main/resources/keycloak.d.ts | 8 +- .../oidc/js/src/main/resources/keycloak.js | 80 +++- examples/cordova-native/.gitignore | 6 + examples/cordova-native/README.md | 36 ++ examples/cordova-native/config.xml | 25 ++ examples/cordova-native/example-realm.json | 61 +++ examples/cordova-native/package-lock.json | 383 ++++++++++++++++++ examples/cordova-native/package.json | 24 ++ examples/cordova-native/www/index.html | 123 ++++++ 9 files changed, 741 insertions(+), 5 deletions(-) create mode 100644 examples/cordova-native/.gitignore create mode 100644 examples/cordova-native/README.md create mode 100644 examples/cordova-native/config.xml create mode 100755 examples/cordova-native/example-realm.json create mode 100644 examples/cordova-native/package-lock.json create mode 100644 examples/cordova-native/package.json create mode 100644 examples/cordova-native/www/index.html diff --git a/adapters/oidc/js/src/main/resources/keycloak.d.ts b/adapters/oidc/js/src/main/resources/keycloak.d.ts index 51d31919cd..eed2bf48e7 100644 --- a/adapters/oidc/js/src/main/resources/keycloak.d.ts +++ b/adapters/oidc/js/src/main/resources/keycloak.d.ts @@ -29,7 +29,7 @@ export = Keycloak; declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance; declare namespace Keycloak { - type KeycloakAdapterName = 'cordova'|'default' | any; + type KeycloakAdapterName = 'cordova' | 'cordova-native' |'default' | any; type KeycloakOnLoad = 'login-required'|'check-sso'; type KeycloakResponseMode = 'query'|'fragment'; type KeycloakResponseType = 'code'|'id_token token'|'code id_token token'; @@ -98,6 +98,12 @@ declare namespace Keycloak { */ responseMode?: KeycloakResponseMode; + /** + * Specifies a default uri to redirect to after login or logout. + * This is currently supported for adapter 'cordova-native' and 'default' + */ + redirectUri?: string; + /** * Set the OpenID Connect flow. * @default standard diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js index 0edde89754..8b147bf9a0 100755 --- a/adapters/oidc/js/src/main/resources/keycloak.js +++ b/adapters/oidc/js/src/main/resources/keycloak.js @@ -46,11 +46,10 @@ kc.authenticated = false; callbackStorage = createCallbackStorage(); + var adapters = ['default', 'cordova', 'cordova-native']; - if (initOptions && initOptions.adapter === 'cordova') { - adapter = loadAdapter('cordova'); - } else if (initOptions && initOptions.adapter === 'default') { - adapter = loadAdapter(); + if (initOptions && adapters.indexOf(initOptions.adapter) > -1) { + adapter = loadAdapter(initOptions.adapter); } else if (initOptions && typeof initOptions.adapter === "object") { adapter = initOptions.adapter; } else { @@ -106,6 +105,10 @@ if (initOptions.timeSkew != null) { kc.timeSkew = initOptions.timeSkew; } + + if(initOptions.redirectUri) { + kc.redirectUri = initOptions.redirectUri; + } } if (!kc.responseMode) { @@ -1339,6 +1342,75 @@ } } + if (type == 'cordova-native') { + loginIframe.enable = false; + + return { + login: function(options) { + var promise = createPromise(); + var loginUrl = kc.createLoginUrl(options); + + universalLinks.subscribe('keycloak', function(event) { + universalLinks.unsubscribe('keycloak'); + window.cordova.plugins.browsertab.close(); + var oauth = parseCallback(event.url); + processCallback(oauth, promise); + }); + + window.cordova.plugins.browsertab.openUrl(loginUrl); + return promise.promise; + }, + + logout: function(options) { + var promise = createPromise(); + var logoutUrl = kc.createLogoutUrl(options); + + universalLinks.subscribe('keycloak', function(event) { + universalLinks.unsubscribe('keycloak'); + window.cordova.plugins.browsertab.close(); + kc.clearToken(); + promise.setSuccess(); + }); + + window.cordova.plugins.browsertab.openUrl(logoutUrl); + return promise.promise; + }, + + register : function(options) { + var promise = createPromise(); + var registerUrl = kc.createRegisterUrl(options); + universalLinks.subscribe('keycloak' , function(event) { + universalLinks.unsubscribe('keycloak'); + window.cordova.plugins.browsertab.close(); + var oauth = parseCallback(event.url); + processCallback(oauth, promise); + }); + window.cordova.plugins.browsertab.openUrl(registerUrl); + return promise.promise; + + }, + + accountManagement : function() { + var accountUrl = kc.createAccountUrl(); + if (typeof accountUrl !== 'undefined') { + window.cordova.plugins.browsertab.openUrl(accountUrl); + } else { + throw "Not supported by the OIDC server"; + } + }, + + redirectUri: function(options) { + if (options && options.redirectUri) { + return options.redirectUri; + } else if (kc.redirectUri) { + return kc.redirectUri; + } else { + return "http://localhost"; + } + } + } + } + throw 'invalid adapter type: ' + type; } diff --git a/examples/cordova-native/.gitignore b/examples/cordova-native/.gitignore new file mode 100644 index 0000000000..3ac935ae6e --- /dev/null +++ b/examples/cordova-native/.gitignore @@ -0,0 +1,6 @@ +platforms +plugins +www/keycloak.js +www/keycloak.json +node_modules +ul_web_hooks diff --git a/examples/cordova-native/README.md b/examples/cordova-native/README.md new file mode 100644 index 0000000000..0510ba8c91 --- /dev/null +++ b/examples/cordova-native/README.md @@ -0,0 +1,36 @@ +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 +------------------------------------ + + cordova platform add android + cordova run android + + +Once the application is opened you can login with username: 'user', and password: 'password'. + + +Troubleshooting +----------------------------------------- + + * You always need to initialize keycloak after the 'deviceready' event. Otherwise Cordova mode won't be enabled for keycloak.js. + * 'http://localhost' should be listed in the allowed redirects in client configuration, but never 'file:///android_asset'. diff --git a/examples/cordova-native/config.xml b/examples/cordova-native/config.xml new file mode 100644 index 0000000000..0a0d962a58 --- /dev/null +++ b/examples/cordova-native/config.xml @@ -0,0 +1,25 @@ + + + Keycloak Auth + Keycloak Cordova Example + Keycloak Team + + + + + + + + + + + + + + + + + + + + diff --git a/examples/cordova-native/example-realm.json b/examples/cordova-native/example-realm.json new file mode 100755 index 0000000000..131ccbd511 --- /dev/null +++ b/examples/cordova-native/example-realm.json @@ -0,0 +1,61 @@ +{ + "realm": "example", + "enabled": true, + "sslRequired": "external", + "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" } + ], + "realmRoles": [ "user" ], + "clientRoles": { + "account": ["view-profile", "manage-account"] + } + } + ], + "roles" : { + "realm" : [ + { + "name": "user", + "description": "User privileges" + }, + { + "name": "admin", + "description": "Administrator privileges" + } + ] + }, + "scopeMappings": [ + { + "client": "cordova", + "roles": ["user"] + } + ], + "clients": [ + { + "clientId": "cordova", + "enabled": true, + "publicClient": true, + "redirectUris": ["android-app://org.keycloak.examples.cordova/https/keycloak-cordova-example.github.io/login"], + "webOrigins": ["localhost"] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "cordova", + "roles": ["view-profile"] + } + ] + } +} diff --git a/examples/cordova-native/package-lock.json b/examples/cordova-native/package-lock.json new file mode 100644 index 0000000000..63bb61364d --- /dev/null +++ b/examples/cordova-native/package-lock.json @@ -0,0 +1,383 @@ +{ + "name": "org.keycloak.examples.cordova", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "cordova-android": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-6.4.0.tgz", + "integrity": "sha1-VK6NpXKKjX5e/MYXLT3MoXvH/n0=", + "requires": { + "android-versions": "1.2.1", + "cordova-common": "2.1.0", + "elementtree": "0.1.6", + "nopt": "3.0.6", + "properties-parser": "0.2.3", + "q": "1.5.0", + "shelljs": "0.5.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true + }, + "android-versions": { + "version": "1.2.1", + "bundled": true + }, + "ansi": { + "version": "0.3.1", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "base64-js": { + "version": "0.0.8", + "bundled": true + }, + "big-integer": { + "version": "1.6.25", + "bundled": true + }, + "bplist-parser": { + "version": "0.1.1", + "bundled": true, + "requires": { + "big-integer": "1.6.25" + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "cordova-common": { + "version": "2.1.0", + "bundled": true, + "requires": { + "ansi": "0.3.1", + "bplist-parser": "0.1.1", + "cordova-registry-mapper": "1.1.15", + "elementtree": "0.1.6", + "glob": "5.0.15", + "minimatch": "3.0.4", + "osenv": "0.1.4", + "plist": "1.2.0", + "q": "1.5.0", + "semver": "5.4.1", + "shelljs": "0.5.3", + "underscore": "1.8.3", + "unorm": "1.4.1" + } + }, + "cordova-registry-mapper": { + "version": "1.1.15", + "bundled": true + }, + "elementtree": { + "version": "0.1.6", + "bundled": true, + "requires": { + "sax": "0.3.5" + } + }, + "glob": { + "version": "5.0.15", + "bundled": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "lodash": { + "version": "3.10.1", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "plist": { + "version": "1.2.0", + "bundled": true, + "requires": { + "base64-js": "0.0.8", + "util-deprecate": "1.0.2", + "xmlbuilder": "4.0.0", + "xmldom": "0.1.27" + } + }, + "properties-parser": { + "version": "0.2.3", + "bundled": true + }, + "q": { + "version": "1.5.0", + "bundled": true + }, + "sax": { + "version": "0.3.5", + "bundled": true + }, + "semver": { + "version": "5.4.1", + "bundled": true + }, + "shelljs": { + "version": "0.5.3", + "bundled": true + }, + "underscore": { + "version": "1.8.3", + "bundled": true + }, + "unorm": { + "version": "1.4.1", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "xmlbuilder": { + "version": "4.0.0", + "bundled": true, + "requires": { + "lodash": "3.10.1" + } + }, + "xmldom": { + "version": "0.1.27", + "bundled": true + } + } + }, + "cordova-plugin-browsertab": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cordova-plugin-browsertab/-/cordova-plugin-browsertab-0.2.0.tgz", + "integrity": "sha1-Hgf5hy4VRnpQ59FKc/79h0+u1ko=" + }, + "cordova-plugin-compat": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cordova-plugin-compat/-/cordova-plugin-compat-1.2.0.tgz", + "integrity": "sha1-C8ZXVyduvZIMASzpIOJ0F3V2Nz4=" + }, + "cordova-plugin-deeplinks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cordova-plugin-deeplinks/-/cordova-plugin-deeplinks-1.1.0.tgz", + "integrity": "sha512-xXixVrXfX9lvhMpi1qlzkiTeOmT7P5LfgqIBUCePYSutuscX+SeRGsVM38J8nhpYIefHAJqz7ULr4hT7tunUCA==", + "requires": { + "mkpath": "1.0.0", + "node-version-compare": "1.0.1", + "plist": "3.0.1", + "rimraf": "2.6.2", + "xml2js": "0.4.19" + } + }, + "cordova-plugin-whitelist": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.3.tgz", + "integrity": "sha1-tehezbv+Wu3tQKG/TuI3LmfZb7Q=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "mkpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", + "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=" + }, + "node-version-compare": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/node-version-compare/-/node-version-compare-1.0.1.tgz", + "integrity": "sha1-2Fv9IPCsreM1d/VmgscQnDTFUM0=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "plist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "requires": { + "base64-js": "1.3.0", + "xmlbuilder": "9.0.7", + "xmldom": "0.1.27" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": "1.2.4", + "xmlbuilder": "9.0.7" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + } + } +} diff --git a/examples/cordova-native/package.json b/examples/cordova-native/package.json new file mode 100644 index 0000000000..796ff56ffa --- /dev/null +++ b/examples/cordova-native/package.json @@ -0,0 +1,24 @@ +{ + "name": "org.keycloak.examples.cordova", + "version": "1.0.0", + "displayName": "Keycloak Auth", + "cordova": { + "platforms": [ + "ios", + "android" + ], + "plugins": { + "cordova-plugin-browsertab": {}, + "cordova-plugin-deeplinks": {}, + "cordova-plugin-whitelist": {} + } + }, + "dependencies": { + "cordova-android": "^6.4.0", + "cordova-ios": "^4.5.4", + "cordova-plugin-browsertab": "^0.2.0", + "cordova-plugin-compat": "^1.2.0", + "cordova-plugin-deeplinks": "^1.1.0", + "cordova-plugin-whitelist": "^1.3.3" + } +} \ No newline at end of file diff --git a/examples/cordova-native/www/index.html b/examples/cordova-native/www/index.html new file mode 100644 index 0000000000..67b0db823d --- /dev/null +++ b/examples/cordova-native/www/index.html @@ -0,0 +1,123 @@ + + + + + + Authentication Example + + + + + + + + + + + + + +