To create a sample web application, you need Python v3 (the sample script prepared on v3.4.3).
NOTE:Ensure to install necessary components like package manager and modules according to the Python version in use as a prerequisite.
The following web application describes the functionalities supported when Advanced Authentication is integrated with OAuth 2.0. OAuth 2.0 server is an authorization and resource server. As an Authorization Server, the OAuth server can prompt the users to go through authentication chains and as a resource server, the OAuth server can prompt the users to provide user details.
You must create the following five files:
Sample script (oauth2_test.py)
from bottle import Bottle, request, run, redirect, SimpleTemplate, template from urllib.parse import urlparse, urlunparse, urlencode,quote import urllib.request import base64 import ssl import json app = Bottle() client_id = 'id-rSCzuBLQgXCATfkXZ4fsedAo8sPsWxSs' client_secret = 'secret-91DpzWFD26RriURR7KJ1pryFx7V9QeDm' redirect_uri = 'http://localhost:8088/' # this app callback URI authorization_endpoint = 'https://192.168.0.151/osp/a/TOP/auth/oauth2/grant' attributes_endpoint = 'https://192.168.0.151/osp/a/TOP/auth/oauth2/getattributes' state = {} @app.get('/getattr') def get_attributes(): params = urlencode({ 'attributes': 'client username userRepository user_dn user_cn mail sid upn netbiosName', 'access_token': state['access_token'] }) url = attributes_endpoint + '?' + params print('getattr url: {}\n'.format(url)) req = urllib.request.Request(url) gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) # avoid cert checking with urllib.request.urlopen(req, context=gcontext) as response: # perform GET request and read response rsp = response.read() attributes = json.loads(rsp.decode('utf-8')) return template('attributes.html', items=attributes.items(), refresh_token=urllib.parse.quote(state['refresh_token'])) @app.get('/') def do_get(): code = request.query.get('code') if code: # got code from OAuth 2 authentication server token = get_token_code(code) state.update(token) return template('token.html', items=token.items(), refresh_token=urllib.parse.quote(token['refresh_token'])) else: return template('main.html') @app.get('/logon') def do_logon(): pr=list(urlparse(authorization_endpoint)) # set query pr[4]=urlencode({ 'response_type': 'code', 'client_id': client_id, 'redirect_uri': redirect_uri }) # perform redirection to OAuth 2 authentication server redirect(urlunparse(pr)) @app.get('/logon-implicit') def do_logon_implicit(): # parse authorization_endpoint URL pr = list(urlparse(authorization_endpoint)) # set query pr[4] = urlencode({ 'response_type': 'token', 'client_id': client_id, }) # perform redirection to OAuth 2 authentication server redirect(urlunparse(pr)) @app.get('/logon-creds') def do_logon_creds(): return template('logonform.html') @app.post('/logon-creds') def do_logon_creds_post(): username = request.forms.get('username') password = request.forms.get('password') token = get_token_password(username, password) state.update(token) return template('token.html', items=token.items(), refresh_token=urllib.parse.quote(token['refresh_token'])) def get_token_password(username, password): # prepare POST parameters - encode them to urlencoded data = urlencode({ 'grant_type': 'password', 'username': username, 'password': password }) data = data.encode('ascii') # data should be bytes resp_text = post_data(data, prepare_headers()) print(resp_text) return json.loads(resp_text) @app.get('/refresh') def do_refresh(): token = refresh_access_token(request.query.get('refresh_token')) state.update(token) return template('token.html', items=token.items(), refresh_token=state.get('refresh_token', '')) def get_token_code(code): # prepare POST parameters - encode them to urlencoded data = urlencode({ 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri }) data = data.encode('ascii') # data should be bytes resp_text = post_data(data, prepare_headers()) print(resp_text) return json.loads(resp_text) def refresh_access_token(refresh_token): print('refresh_token: {}'.format(refresh_token)) # prepare POST parameters - encode them to urlencoded data = urlencode({ 'grant_type': 'refresh_token', 'refresh_token': refresh_token, }) data = data.encode('ascii') # data should be bytes resp_text = post_data(data, prepare_headers()) print(resp_text) return json.loads(resp_text) def prepare_headers(use_content_type_hdr = True): hdrs = { 'Authorization': 'Basic {}'.format(base64.b64encode( '{}:{}'.format(quote(client_id, safe=''), quote(client_secret, safe='')).encode('ascii')).decode( 'ascii')), } if use_content_type_hdr: hdrs.update({'Content-type': 'application/x-www-form-urlencoded'}) return hdrs def post_data(data, headers): print('post_data\nheaders:\n{}\ndata:\n{}'.format(headers, data)) req = urllib.request.Request(authorization_endpoint, data, headers) gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) # avoid cert checking with urllib.request.urlopen(req, context=gcontext) as response: # perform POST request and read response rsp = response.read() return rsp.decode('utf-8') run(app, host='0.0.0.0', port=8088)
NOTE:In the script, you must change the values for client_id, client_secret, and Advanced Authentication server address in authorization_endpoint and attributes_endpoint (lines 10-14).
Main menu (main.html)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> //<![CDATA[ function getHashParam(name) { var hash = window.location.hash; if (hash) { if (name = (new RegExp('[#&]' + encodeURIComponent(name) + '=([^&]*)')).exec(hash)) return decodeURIComponent(name[1]); } } function showResult() { if (window.location.hash) { document.getElementById('result').innerHTML = '<table border="1">'+ '<tr><td>access_token</td><td>'+getHashParam('access_token')+'</td></tr>'+ '<tr><td>token_type</td><td>'+getHashParam('token_type')+'</td></tr>'+ '<tr><td>expires_in</td><td>'+getHashParam('expires_in')+'</td></tr>'+ '</table>'; } else { document.getElementById('result').innerHTML = 'Implicit granted token is not found'; } } ]]//> </script> </head> <body onload="showResult();"> <div id="result">result</div><br/> <br/> Click <a href="/logon">here</a> to obtain an authentication token through Authorization Code Grant<br/> Click <a href="/logon-implicit">here</a> to obtain an authentication token through Implicit Grant (the token will be received in hash part of THIS page)<br/> Click <a href="/logon-creds">here</a> to obtain an authentication token through Resource Owner Password Credentials Grant<br/> </body> </html>
Token information (token.html)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> Token<br/> <table border="1"> % for k, v in items: <tr> <td>{{k}}</td> <td>{{v}}</td> </tr> % end </table> <br/> <a href="/getattr">Get attributes</a><br/> <a href="/refresh?refresh_token={{refresh_token}}">Refresh token</a> </body> </html>
Attributes information (attributes.html)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> Attributes<br/> <table border="1"> % for k, v in items: <tr> <td>{{k}}</td> <td>{{v}}</td> </tr> % end </table> <br/> <a href="/refresh?refresh_token={{refresh_token}}">Refresh token</a> </body> </html>
Logon form for Resource Owner Password Credentials Grant mode (logonform.html)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <form method="post" action="/logon-creds"> User name: <input type="text" name="username"><br/> Password: <input type="password" name="password"><br/> <input type="submit"> </form> </body> </html>