2 * Copyright (c) 2015, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 console.log("Loading navigator.gssweb.js - #4");
37 var GSSWeb = (function () {
38 function GSSWeb(config) {
39 this.serverPath = config.serverPath;
40 this.credential = config.credential;
41 this.appTag = config.appTag || "GSSWeb-" + navigator.generateNonce();
42 this.error = config.error || function (err) {
45 this.success = config.success;
47 this.version = "0.0.1";
48 this.authenticationState = false;
50 this.serverToken = "";
52 this.xhr = new XMLHttpRequest();
54 this.gss = new navigator.gssEap({
56 error: this.handleGSSError.bind(this)
59 /* What to invoke when the underlying GSS library
62 GSSWeb.prototype.handleGSSError =
63 function (major, minor, errMsg, appTag) {
64 this.error(errMsg, appTag);
67 /* The basic authenticate function.
68 * Takes no arguments, as all should be supplied
71 GSSWeb.prototype.authenticate = function () {
73 // Ensure that the callbacks exist well
74 if ( "function" != typeof(this.error) )
76 // I can't even call my error function! All that can be done
78 throw("Error function not supplied to navigator.gssweb object!");
80 if ( "function" != typeof(this.success) )
82 // OK, so we have an error function; use it.
84 "Success function not supplied to navigator.gssweb object!"
87 if ( ! this.presentString(this.serverPath) )
89 this.error("Server path not supplied to navigator.gssweb object!");
94 this.nonce = navigator.generateNonce();
96 // Start off the cascade by getting the
97 // GSS name of the server
98 this.authGetServerName();
101 GSSWeb.prototype.authGetServerName = function () {
102 this.gss.import_name({
103 name: "HTTP@" + window.location.hostname,
104 success: this.authReceiveServerName.bind(this)
107 GSSWeb.prototype.authReceiveServerName = function (data, appTag) {
108 this.serverName = data.gss_name;
110 /* Either move on to acquire_cred because we have been
111 * supplied a credential, or move on to init_sec_context
114 if ( this.presentString(this.credential) )
115 this.authGetClientName();
117 this.authInitSecContext();
120 GSSWeb.prototype.authGetClientName = function () {
121 this.gss.import_name({
122 name: this.credential,
123 success: this.authReceiveClientName.bind(this)
126 GSSWeb.prototype.authReceiveClientName = function (data, appTag) {
127 this.clientName = data.gss_name;
129 // Next up: Get the local credential
130 this.authAcquireCred();
133 GSSWeb.prototype.authAcquireCred = function () {
134 this.gss.acquire_cred({
135 desired_name: this.clientName,
137 success: this.authReceiveClientCred.bind(this)
140 GSSWeb.prototype.authReceiveClientCred =
141 function (cred, actual_mechs, lifetime_rec) {
142 this.clientCred = cred;
144 this.authInitSecContext();
147 GSSWeb.prototype.authInitSecContext = function () {
149 target_name: this.serverName,
150 success: this.sendTokenToServer.bind(this)
153 if ("" != this.clientCred) {
154 params.cred_handle = this.clientCred;
156 if ("" != this.serverToken) {
157 params.input_token = this.serverToken;
159 if ("" != this.context) {
160 params.context_handle = this.context;
163 this.gss.init_sec_context(params);
166 GSSWeb.prototype.sendTokenToServer =
169 this.clientToken = data.output_token;
170 this.context = data.context_handle;
172 var msg = "nonce=" + this.nonce +
173 "&token=" + encodeURIComponent(this.clientToken);
175 this.xhr.open("POST", this.serverPath, true);
177 this.xhr.setRequestHeader(
179 'application/x-www-form-urlencoded'
181 this.xhr.onreadystatechange = this.recvTokenFromServer.bind(this);
186 GSSWeb.prototype.recvTokenFromServer = function () {
187 // Only care when we're ready
188 if (this.xhr.readyState != 4) {
192 switch (this.xhr.status) {
195 var serverResponse = JSON.parse(this.xhr.responseText);
196 var decoded = window.atob(serverResponse.application.data);
197 this.authenticationState = true;
200 serverResponse.application["content-type"],
206 var serverResponse = JSON.parse(this.xhr.responseText);
207 this.serverToken = serverResponse.gssweb.token;
208 this.authInitSecContext();
211 // We have some server-reported error
213 window.location.hostname +
214 " reported an error; aborting",
218 // Destroy the GSS context.
219 this.context = undefined;
224 /*************************************
226 *************************************/
227 // return true if the variable is a non-empty string
228 GSSWeb.prototype.presentString = function(str)
231 "string" == typeof(str) &&
239 navigator.gssweb = GSSWeb;