keycloak javascript adaptor study notes

Official document address:

http://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter

 

Sample source file address 

C:\Users\huangqiqing\Desktop\keycloak\安装包\keycloak-demo-3.4.3.Final\examples\js-console\src\main\webapp


 You can directly modify index.html here. After modification, enter the path:

 

C:\Users\huangqiqing\Desktop\keycloak\安装包\keycloak-demo-3.4.3.Final\examples\js-console

 

 

With the command: mvn install wildfly:deploy   , the application can be republished to wildfly (original Jboss), and it will take effect without restarting.

 

 

Keycloak.json is the client information corresponding to the current javascript application in keycloak, which is read when the application is initialized.



 

 

 


  

 

 Keycloak.js is a javascript adaptor provided by keycloak,

Javascript applications can be copied to their own applications,

You can also directly reference keycloak (/auth/js/keycloak.js),

It is recommended to directly refer to keycloak (when keycloak is updated, the javascript adaptor can be automatically updated synchronously)

 

 

 

One important thing to note about using client-side applications is that the client has to be a public client as there is no secure way to store client credentials in a client-side application. 

很重要的一点需要注意,客户端应用(如javascript应用)在keycloak中注册时,必须将AccessType置为public,因为客户端应用存储client Credentials 不安全。

 

 

关于 Valid Redirect URLs

Valid URI pattern a browser can redirect to after a successful login or logout. Simple wildcards【通配符】 are allowed i.e. 'http://example.com/*'. Relative path can be specified too i.e. /my/relative/path/*. Relative paths are relative to the client root URL, or if none is specified the auth server root URL is used. For SAML, you must set valid URI patterns if you are relying on the consumer service URL embedded with the login request

 

关于Base URI

 

Default URL to use when the auth server needs to redirect or link back to the client



 

 

Keycloak.json在线生成、下载



 

 

三种onload模式

1、  默认值

需要显示地调用 login函数,否则不与keycloak交互。

2、  login-required

进入javascript应用时,会检查keycloak是否已登录

如果keycloak未登录,会强制进入keycloak登录页面。

如果keycloak已登录,直接显示已登录状态。

3、  check-sso

进入javascript应用时,会检查keycloak是否已登录,

如果keycloak已登录,javascript应用显示已登录状态。

如果keycloak未登录,javascript显示未登录状态。

 

 

示例代码

 

 

 Session Status iframe

By default, the JavaScript adapter creates a hidden iframe that is used to detect if a Single-Sign Out has occurred.

This does not require any network traffic, instead the status is retrieved by looking at a special status cookie.

This feature can be disabled by setting checkLoginIframe: false in the options passed to the init method.

 

You should not rely on looking at this cookie directly. It’s format can change and it’s also associated with the URL of the Keycloak server, not your application.

 
 

服务调用

 After the user is authenticated the application can make requests to RESTful services secured by Keycloak by including the bearer token in the Authorization header

用户认证通过后,就可以调用被keycloak保护的RESTful 服务了。

调用方式:添加header参数 Authorization,参数值:bearer keycloak.token

 

官方实例

 

var loadData = function () {
    document.getElementById('username').innerText = keycloak.subject;

    var url = 'http://localhost:8080/restful-service';

    var req = new XMLHttpRequest();
    req.open('GET', url, true);
    req.setRequestHeader('Accept', 'application/json');
    req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);

    req.onreadystatechange = function () {
        if (req.readyState == 4) {
            if (req.status == 200) {
                alert('Success');
            } else if (req.status == 403) {
                alert('Forbidden');
            }
        }
    }

    req.send();
};

 

 本地Postman测试

 



 

 

 

需要注意的一点,token是有有效期的,有时,调用REST服务之前,需要首先刷新下token。

 

 

官方示例

keycloak.updateToken(30).success(function() {
    loadData();
}).error(function() {
    alert('Failed to refresh token');
});

 

 

 关于刷新token的两个函数



 使用过期token调用受keycloak保护的RESTFUL Service



 

 

Callback Events 回调事件

 

The javascript adapter supports setting callback listeners for certain events.

 

For example:

 

keycloak.onAuthSuccess = function() { alert('authenticated'); }

 

The available events are:

 

onReady(authenticated) - Called when the adapter is initialized.

 

onAuthSuccess - Called when a user is successfully authenticated.

 

onAuthError - Called if there was an error during authentication.

 

onAuthRefreshSuccess - Called when the token is refreshed.

 

onAuthRefreshError - Called if there was an error while trying to refresh the token.

 

onAuthLogout - Called if the user is logged out (will only be called if the session status iframe is enabled, or in Cordova mode).

 

onTokenExpired - Called when the access token is expired. If a refresh token is available the token can be refreshed with updateToken, or in cases where it is not (that is, with implicit flow) you can redirect to login screen to obtain a new access token.

 

示例,监听到accessToken过期时,自动刷新accessToken。

   //token过期时回调
   keycloak.onTokenExpired = function () {
       alert('Access token expired.');
       //刷新accessToken
       keycloak.updateToken(0).success(function(refreshed) {
           if (refreshed) {
        	   alert('refresh success.');
           } else {
        	   alert('refresh failed.');
           }
       }).error(function() {
    	   alert('Failed to refresh token');
       });
   };

 

 

官方javascript示例 index.html



 

源码

<html>
<head>
    <script src="/auth/js/keycloak.js"></script>
</head>
<body>

<div>
    <button onclick="keycloak.login()">Login</button>
    <button onclick="keycloak.logout()">Logout</button>
    <button onclick="keycloak.register()">Register</button>
    <button onclick="refreshToken(9999)">Refresh Token</button>
    <button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
    <button onclick="loadProfile()">Get Profile</button>
    <button onclick="loadUserInfo()">Get User Info</button>
    <button onclick="output(keycloak.tokenParsed)">Show Token</button>
    <button onclick="output(keycloak.refreshTokenParsed)">Show Refresh Token</button>
    <button onclick="output(keycloak.idTokenParsed)">Show ID Token</button>
    <button onclick="showExpires()">Show Expires</button>
    <button onclick="output(keycloak)">Show Details</button>
    <button onclick="output(keycloak.createLoginUrl())">Show Login URL</button>
    <button onclick="output(keycloak.createLogoutUrl())">Show Logout URL</button>
    <button onclick="output(keycloak.createRegisterUrl())">Show Register URL</button>
</div>

<h2>Result</h2>
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px; word-wrap: break-word; white-space: pre-wrap;" id="output"></pre>

<h2>Events</h2>
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px; word-wrap: break-word; white-space: pre-wrap;" id="events"></pre>


<script>
    function loadProfile() {
        keycloak.loadUserProfile().success(function(profile) {
            output(profile);
        }).error(function() {
            output('Failed to load profile');
        });
    }

    function loadUserInfo() {
        keycloak.loadUserInfo().success(function(userInfo) {
            output(userInfo);
        }).error(function() {
            output('Failed to load user info');
        });
    }

    function refreshToken(minValidity) {
        keycloak.updateToken(minValidity).success(function(refreshed) {
            if (refreshed) {
                output(keycloak.tokenParsed);
            } else {
                output('Token not refreshed, valid for ' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
            }
        }).error(function() {
            output('Failed to refresh token');
        });
    }

    function showExpires() {
        if (!keycloak.tokenParsed) {
            output("Not authenticated");
            return;
        }

        var o = 'Token Expires:\t\t' + new Date((keycloak.tokenParsed.exp + keycloak.timeSkew) * 1000).toLocaleString() + '\n';
        o += 'Token Expires in:\t' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds\n';

        if (keycloak.refreshTokenParsed) {
            o += 'Refresh Token Expires:\t' + new Date((keycloak.refreshTokenParsed.exp + keycloak.timeSkew) * 1000).toLocaleString() + '\n';
            o += 'Refresh Expires in:\t' + Math.round(keycloak.refreshTokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds';
        }

        output(o);
    }

    function output(data) {
        if (typeof data === 'object') {
            data = JSON.stringify(data, null, '  ');
        }
        document.getElementById('output').innerHTML = data;
    }

    function event(event) {
        var e = document.getElementById('events').innerHTML;
        document.getElementById('events').innerHTML = new Date().toLocaleString() + "\t" + event + "\n" + e;
    }

    var keycloak = Keycloak();

    keycloak.onAuthSuccess = function () {
        event('Auth Success');
    };

    keycloak.onAuthError = function (errorData) {
        event("Auth Error: " + JSON.stringify(errorData) );
    };

    keycloak.onAuthRefreshSuccess = function () {
        event('Auth Refresh Success');
    };

    keycloak.onAuthRefreshError = function () {
        event('Auth Refresh Error');
    };

    keycloak.onAuthLogout = function () {
        event('Auth Logout');
    };

    keycloak.onTokenExpired = function () {
        event('Access token expired.');
    };

    // Flow can be changed to 'implicit' or 'hybrid', but then client must enable implicit flow in admin console too 
    var initOptions = {
        responseMode: 'fragment',
        flow: 'standard',
		//
        //onLoad:'login-required'
        onLoad: 'check-sso'
    };

    keycloak.init(initOptions).success(function(authenticated) {
        output('Init Success (' + (authenticated ? 'Authenticated' : 'Not Authenticated') + ')');
    }).error(function() {
        output('Init Error');
    });

</script>
</body>
</html>

 

 

 特别说明:

keycloak初始化相关代码,一定要放到header标签里,一定要保证先于其他javascript代码执行,否则可能出现莫名其妙的问题。

 

 

 

 

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326119442&siteId=291194637