Fix the security issue.
[aai/esr-server.git] / esr-mgr / src / main / resources / api-doc / lib / swagger-oauth.js
1 /*
2  * Copyright 2016 ZTE Corporation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16  */
17 var appName;
18 var popupMask;
19 var popupDialog;
20 var clientId;
21 var realm;
22 var oauth2KeyName;
23 var redirect_uri;
24
25 function handleLogin() {
26   var scopes = [];
27
28   var auths = window.swaggerUi.api.authSchemes || window.swaggerUi.api.securityDefinitions;
29   if(auths) {
30     var key;
31     var defs = auths;
32     for(key in defs) {
33       var auth = defs[key];
34       if(auth.type === 'oauth2' && auth.scopes) {
35         oauth2KeyName = key;
36         var scope;
37         if(Array.isArray(auth.scopes)) {
38           // 1.2 support
39           var i;
40           for(i = 0; i < auth.scopes.length; i++) {
41             scopes.push(auth.scopes[i]);
42           }
43         }
44         else {
45           // 2.0 support
46           for(scope in auth.scopes) {
47             scopes.push({scope: scope, description: auth.scopes[scope]});
48           }
49         }
50       }
51     }
52   }
53
54   if(window.swaggerUi.api
55     && window.swaggerUi.api.info) {
56     appName = window.swaggerUi.api.info.title;
57   }
58
59   popupDialog = $(
60     [
61       '<div class="api-popup-dialog">',
62       '<div class="api-popup-title">Select OAuth2.0 Scopes</div>',
63       '<div class="api-popup-content">',
64         '<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.',
65           '<a href="#">Learn how to use</a>',
66         '</p>',
67         '<p><strong>' + appName + '</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>',
68         '<ul class="api-popup-scopes">',
69         '</ul>',
70         '<p class="error-msg"></p>',
71         '<div class="api-popup-actions"><button class="api-popup-authbtn api-button green" type="button">Authorize</button><button class="api-popup-cancel api-button gray" type="button">Cancel</button></div>',
72       '</div>',
73       '</div>'].join(''));
74   $(document.body).append(popupDialog);
75
76   popup = popupDialog.find('ul.api-popup-scopes').empty();
77   for (i = 0; i < scopes.length; i ++) {
78     scope = scopes[i];
79     str = '<li><input type="checkbox" id="scope_' + i + '" scope="' + scope.scope + '"/>' + '<label for="scope_' + i + '">' + scope.scope;
80     if (scope.description) {
81       str += '<br/><span class="api-scope-desc">' + scope.description + '</span>';
82     }
83     str += '</label></li>';
84     popup.append(str);
85   }
86
87   var $win = $(window),
88     dw = $win.width(),
89     dh = $win.height(),
90     st = $win.scrollTop(),
91     dlgWd = popupDialog.outerWidth(),
92     dlgHt = popupDialog.outerHeight(),
93     top = (dh -dlgHt)/2 + st,
94     left = (dw - dlgWd)/2;
95
96   popupDialog.css({
97     top: (top < 0? 0 : top) + 'px',
98     left: (left < 0? 0 : left) + 'px'
99   });
100
101   popupDialog.find('button.api-popup-cancel').click(function() {
102     popupMask.hide();
103     popupDialog.hide();
104     popupDialog.empty();
105     popupDialog = [];
106   });
107
108   $('button.api-popup-authbtn').unbind();
109   popupDialog.find('button.api-popup-authbtn').click(function() {
110     popupMask.hide();
111     popupDialog.hide();
112
113     var authSchemes = window.swaggerUi.api.authSchemes;
114     var host = window.location;
115     var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
116     var redirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
117     var url = null;
118
119     for (var key in authSchemes) {
120       if (authSchemes.hasOwnProperty(key)) {
121         var flow = authSchemes[key].flow;
122         
123         if(authSchemes[key].type === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) {
124           var dets = authSchemes[key];
125           url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');
126           window.swaggerUi.tokenName = dets.tokenName || 'access_token';
127           window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);          
128         }
129         else if(authSchemes[key].grantTypes) {
130           // 1.2 support
131           var o = authSchemes[key].grantTypes;
132           for(var t in o) {
133             if(o.hasOwnProperty(t) && t === 'implicit') {
134               var dets = o[t];
135               var ep = dets.loginEndpoint.url;
136               url = dets.loginEndpoint.url + '?response_type=token';
137               window.swaggerUi.tokenName = dets.tokenName;
138             }
139             else if (o.hasOwnProperty(t) && t === 'accessCode') {
140               var dets = o[t];
141               var ep = dets.tokenRequestEndpoint.url;
142               url = dets.tokenRequestEndpoint.url + '?response_type=code';
143               window.swaggerUi.tokenName = dets.tokenName;
144             }
145           }
146         }
147       }
148     }
149     var scopes = []
150     var o = $('.api-popup-scopes').find('input:checked');
151
152     for(k =0; k < o.length; k++) {
153       var scope = $(o[k]).attr('scope');
154       
155       if (scopes.indexOf(scope) === -1)
156         scopes.push(scope);
157     }
158
159     window.enabledScopes=scopes;
160
161     redirect_uri = redirectUrl;
162
163     url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
164     url += '&realm=' + encodeURIComponent(realm);
165     url += '&client_id=' + encodeURIComponent(clientId);
166     url += '&scope=' + encodeURIComponent(scopes);
167
168     window.open(url);
169   });
170
171   popupMask.show();
172   popupDialog.show();
173   return;
174 }
175
176
177 function handleLogout() {
178   for(key in window.authorizations.authz){
179     window.authorizations.remove(key)
180   }
181   window.enabledScopes = null;
182   $('.api-ic.ic-on').addClass('ic-off');
183   $('.api-ic.ic-on').removeClass('ic-on');
184
185   // set the info box
186   $('.api-ic.ic-warning').addClass('ic-error');
187   $('.api-ic.ic-warning').removeClass('ic-warning');
188 }
189
190 function initOAuth(opts) {
191   var o = (opts||{});
192   var errors = [];
193
194   appName = (o.appName||errors.push('missing appName'));
195   popupMask = (o.popupMask||$('#api-common-mask'));
196   popupDialog = (o.popupDialog||$('.api-popup-dialog'));
197   clientId = (o.clientId||errors.push('missing client id'));
198   realm = (o.realm||errors.push('missing realm'));
199
200   if(errors.length > 0){
201     log('auth unable initialize oauth: ' + errors);
202     return;
203   }
204
205   $('pre code').each(function(i, e) {hljs.highlightBlock(e)});
206   $('.api-ic').unbind();
207   $('.api-ic').click(function(s) {
208     if($(s.target).hasClass('ic-off'))
209       handleLogin();
210     else {
211       handleLogout();
212     }
213     false;
214   });
215 }
216
217 function processOAuthCode(data) {
218   var params = {
219     'client_id': clientId,
220     'code': data.code,
221     'grant_type': 'authorization_code',
222     'redirect_uri': redirect_uri
223   }
224   $.ajax(
225   {
226     url : window.swaggerUi.tokenUrl,
227     type: "POST",
228     data: params,
229     success:function(data, textStatus, jqXHR) 
230     {
231       onOAuthComplete(data);
232     },
233     error: function(jqXHR, textStatus, errorThrown) 
234     {
235       onOAuthComplete("");
236     }
237   });
238 }
239
240 function onOAuthComplete(token) {
241   if(token) {
242     if(token.error) {
243       var checkbox = $('input[type=checkbox],.secured')
244       checkbox.each(function(pos){
245         checkbox[pos].checked = false;
246       });
247       alert(token.error);
248     }
249     else {
250       var b = token[window.swaggerUi.tokenName];
251       if(b){
252         // if all roles are satisfied
253         var o = null;
254         $.each($('.auth #api_information_panel'), function(k, v) {
255           var children = v;
256           if(children && children.childNodes) {
257             var requiredScopes = [];
258             $.each((children.childNodes), function (k1, v1){
259               var inner = v1.innerHTML;
260               if(inner)
261                 requiredScopes.push(inner);
262             });
263             var diff = [];
264             for(var i=0; i < requiredScopes.length; i++) {
265               var s = requiredScopes[i];
266               if(window.enabledScopes && window.enabledScopes.indexOf(s) == -1) {
267                 diff.push(s);
268               }
269             }
270             if(diff.length > 0){
271               o = v.parentNode;
272               $(o.parentNode).find('.api-ic.ic-on').addClass('ic-off');
273               $(o.parentNode).find('.api-ic.ic-on').removeClass('ic-on');
274
275               // sorry, not all scopes are satisfied
276               $(o).find('.api-ic').addClass('ic-warning');
277               $(o).find('.api-ic').removeClass('ic-error');
278             }
279             else {
280               o = v.parentNode;
281               $(o.parentNode).find('.api-ic.ic-off').addClass('ic-on');
282               $(o.parentNode).find('.api-ic.ic-off').removeClass('ic-off');
283
284               // all scopes are satisfied
285               $(o).find('.api-ic').addClass('ic-info');
286               $(o).find('.api-ic').removeClass('ic-warning');
287               $(o).find('.api-ic').removeClass('ic-error');          
288             }
289           }
290         });
291         window.authorizations.add(oauth2KeyName, new ApiKeyAuthorization('Authorization', 'Bearer ' + b, 'header'));
292       }
293     }
294   }
295 }