Commit ff93ed77 authored by janis.streib's avatar janis.streib 🦉
Browse files

ADD: OIC login

parent 69859523
Pipeline #94798 passed with stages
in 7 minutes and 14 seconds
export default { export default {
NETDB_API_BASE_URL: "/api/3.0/" NETDB_API_BASE_URL: "/api/3.0/",
ENABLE_OIC: true,
} }
import Axios from 'axios'; import Axios from 'axios';
import config from '@/../netvs.config'
const LOGIN_RESOURCE = '/api/login'; const LOGIN_RESOURCE = '/api/login';
const LOGOUT_RESOURCE = '/api/logout'; const LOGOUT_RESOURCE = '/api/logout';
export default { export default {
login(username, password) { login(username, password) {
if (config.ENABLE_OIC) {
return Axios.post(LOGIN_RESOURCE)
}
return Axios.post(LOGIN_RESOURCE, {'username': username, 'password': password}) return Axios.post(LOGIN_RESOURCE, {'username': username, 'password': password})
}, },
logout(token_pk) { logout(token_pk) {
......
...@@ -30,6 +30,16 @@ export default new Router({ ...@@ -30,6 +30,16 @@ export default new Router({
} }
} }
}, },
{
path: '/oic_login',
name: 'login',
component: () => import('./views/OICLogin.vue'),
meta: {
resolveName: function () {
return "OIC Login"
}
}
},
{ {
path: '/user/tokens', path: '/user/tokens',
name: 'tokens', name: 'tokens',
......
...@@ -2,29 +2,32 @@ ...@@ -2,29 +2,32 @@
<div class="login"> <div class="login">
<p>Willkommen auf der Eingangsseite zur Selbstverwaltung der aktuell angebotenen Basisdienste für das <p>Willkommen auf der Eingangsseite zur Selbstverwaltung der aktuell angebotenen Basisdienste für das
KITnet.</p> KITnet.</p>
<div class="jumbotron"> <b-jumbotron>
<div class="pull-left"> <div class="pull-left">
<img class="hidden-xs hidden-sm pull-left" src="@/assets/img/scc_logo.png"/> <img class="hidden-xs hidden-sm pull-left" src="@/assets/img/scc_logo.png"/>
</div> </div>
<b-form @submit="login"> <b-form @submit="login">
<div class="pull-left logincont"> <div class="pull-left logincont">
<label for="username">KIT-Account</label> <template v-if="!use_oic">
<input id="username" class="form-control" v-model="username" autofocus type="text"/> <label for="username">KIT-Account</label>
<label for="password">Passwort</label> <input id="username" class="form-control" v-model="username" autofocus type="text"/>
<input id="password" class="form-control" v-model="password" type="password"/><br/> <label for="password">Passwort</label>
<input id="password" class="form-control" v-model="password" type="password"/><br/>
</template>
<button class="btn btn-outline-primary pull-right" type="submit"><i <button class="btn btn-outline-primary pull-right" type="submit"><i
class="fa fa-sign-in" aria-hidden="true"> </i> Anmelden class="fa fa-sign-in" aria-hidden="true"> </i> Anmelden
</button> </button>
</div> </div>
</b-form> </b-form>
<span class="clearfix"></span> <span class="clearfix"></span>
</div> </b-jumbotron>
</div> </div>
</template> </template>
<script> <script>
import LoginService from '@/api-services/login.service' import LoginService from '@/api-services/login.service'
import router from '@/router' import router from '@/router'
import config from '@/../netvs.config'
export default { export default {
name: 'net_suite_login', name: 'net_suite_login',
...@@ -32,13 +35,14 @@ ...@@ -32,13 +35,14 @@
return { return {
username: '', username: '',
password: '', password: '',
prevRoute: null prevRoute: null,
use_oic: config.ENABLE_OIC
} }
}, },
beforeRouteEnter(to, from, next) { beforeRouteEnter(to, from, next) {
next(vm => { next(vm => {
window.console.debug(from.path) window.console.debug(from.path)
if(from.path != '/login') { if (from.path != '/login') {
vm.prevRoute = from vm.prevRoute = from
} }
}) })
...@@ -48,7 +52,11 @@ ...@@ -48,7 +52,11 @@
ev.preventDefault() ev.preventDefault()
let self = this let self = this
LoginService.login(this.username, this.password).then((response) => { LoginService.login(this.username, this.password).then((response) => {
if(response.data.login != null) { if(response.data.status == 'usr_redir') {
window.location = response.data.url
return
}
if (response.data.login != null) {
self.$store.commit('login', {user: response.data.login, token: response.data.token}) self.$store.commit('login', {user: response.data.login, token: response.data.token})
router.push(self.prevRoute.path) router.push(self.prevRoute.path)
} else { } else {
......
<template>
<div class="login">
<h1>Logging in...</h1>
</div>
</template>
<script>
import LoginService from '@/api-services/login.service'
export default {
name: 'net_suite_login',
created: function () {
let self = this
LoginService.login().then((response) => {
if (response.data.status == 'usr_redir') {
window.location = response.data.url
return
}
if (response.data.login != null) {
self.$store.commit('login', {user: response.data.login, token: response.data.token})
self.$router.push('/')
} else {
// TODO: invalid login
}
})
}
}
</script>
...@@ -8,7 +8,7 @@ module.exports = { ...@@ -8,7 +8,7 @@ module.exports = {
'^/api': { '^/api': {
target: 'https://netvs-devel-devel.scc.kit.edu', target: 'https://netvs-devel-devel.scc.kit.edu',
//target: 'http://localhost:5000 //target: 'http://localhost:5000
changeOrigin: true changeOrigin: false
} }
} }
} }
......
...@@ -7,7 +7,7 @@ import sys ...@@ -7,7 +7,7 @@ import sys
import os import os
import inspect import inspect
import subprocess import subprocess
from .model import DBObject, MetaDBObject from .model import DBObject, MetaDBObject, SimpleKITUser
import importlib import importlib
import kitnet.lib.netdd import kitnet.lib.netdd
import kitnet.lib.host_oper_mode_data import kitnet.lib.host_oper_mode_data
...@@ -39,7 +39,7 @@ class ModMetaData(object): ...@@ -39,7 +39,7 @@ class ModMetaData(object):
class CustomJSONEncoder(JSONEncoder): class CustomJSONEncoder(JSONEncoder):
def default(self, obj): def default(self, obj):
if isinstance(obj, DBObject): if isinstance(obj, DBObject) or isinstance(obj, SimpleKITUser):
return {k: v for (k, v) in obj.__dict__.items() if not k.startswith('_')} return {k: v for (k, v) in obj.__dict__.items() if not k.startswith('_')}
elif isinstance(obj, ipaddress.IPv4Network) or isinstance(obj, ipaddress.IPv6Network): elif isinstance(obj, ipaddress.IPv4Network) or isinstance(obj, ipaddress.IPv6Network):
return {'address': str(obj), 'netmask': obj.netmask, 'broadcast_address': obj.broadcast_address} return {'address': str(obj), 'netmask': obj.netmask, 'broadcast_address': obj.broadcast_address}
......
from flask import Blueprint from flask import Blueprint
from net_suite import app
login_url = 'login_oic.login' login_url = 'login_oic.login'
login_oic = Blueprint('login_oic', __name__) login_oic = Blueprint('login_oic', __name__)
from oic.oic import Client
from oic import rndstr
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
state = rndstr()
nonce = rndstr()
client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
provider_info = client.provider_config('https://oidc.scc.kit.edu/auth/realms/kit/')
registration_response = client.register(
provider_info["registration_endpoint"])
args = {
"client_id": client.client_id,
"response_type": "code",
"scope": ["openid"],
"nonce": nonce,
"redirect_uri": client.registration_response["redirect_uris"][0],
"state": state
}
print(registration_response)
auth_req = client.construct_AuthorizationRequest(request_args=args)
login_url = auth_req.request(client.authorization_endpoint)
from . import views from . import views
...@@ -2,30 +2,123 @@ from flask import render_template, request, redirect, abort, flash, jsonify ...@@ -2,30 +2,123 @@ from flask import render_template, request, redirect, abort, flash, jsonify
from net_suite import db from net_suite import db
from net_suite.views import get_db_conn from net_suite.views import get_db_conn
from net_suite.model import * from net_suite.model import *
from . import login_oic from . import login_oic, app
from oic.oic.message import RegistrationResponse, AuthorizationResponse
from oic.oic import Client
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic import rndstr
from oic.utils.http_util import Redirect
@login_oic.route('/api/login', methods=['GET', 'POST']) def get_client():
oic_client = Client(client_authn_method=CLIENT_AUTHN_METHOD)
oic_provider_info = oic_client.provider_config(app.config.get('OIC_ENDPOINT'))
info = {"client_id": app.config.get('OIC_CLIENT_ID'), "client_secret": app.config.get('OIC_CLIENT_SECRET')}
client_reg = RegistrationResponse(**info)
oic_client.store_registration_info(client_reg)
return oic_client
def get_authorization_response(client):
authorization_response = client.parse_response(
AuthorizationResponse,
info=request.args,
sformat='dict')
return authorization_response
@login_oic.route('/api/login', methods=['POST'])
def api_login(): def api_login():
s = request.environ['beaker.session'] s = request.environ['beaker.session']
if 'login' not in s: if 'login' not in s:
if request.method == 'POST': oic_client = get_client()
username = request.json['username'].strip() s["state"] = rndstr()
password = request.json['password'] s["nonce"] = rndstr()
if ldap_con.login(username=username, password=password): debug_t_host = request.environ.get('HTTP_ORIGIN', None)
user = DBMgr.get_by_login_name(db, get_db_conn(), username) s.save()
if user is not None: args = {
s['login'] = user "client_id": oic_client.client_id,
s['plan'] = Transaction() "response_type": "code",
s.save() "scope": ["openid", 'profile', 'email'],
return jsonify({'login': user}) "nonce": s["nonce"],
else: "redirect_uri": app.config.get('DEBUG_OIC_REDIR')+'/'+debug_t_host.split('//',1)[1] if db.host_omdl.OP_ENV_IS_DEVEL and request.host.split(':')[0] == 'localhost' else app.config.get('OIC_REDIR'),
user = ldap_con.get_simple_kit_user(username=username) "state": s["state"]
s['login'] = user }
s['plan'] = Transaction() auth_req = oic_client.construct_AuthorizationRequest(request_args=args)
s.save() login_url = auth_req.request(oic_client.authorization_endpoint)
return jsonify({'login': user}) return jsonify({'status': 'usr_redir', 'url': login_url})
else: if not 'login_token' in s and not isinstance(s['login'], SimpleKITUser):
return jsonify({'login': None}) s['login_token'] = s['login'].create_session_token(db, get_db_conn(), False)
return jsonify({'login': s['login']}) s.save()
return jsonify({'login': s['login'], 'token': s.get('login_token', None)})
def user_from_userinfo(db, conn, userinfo):
user = DBMgr.get_by_login_name(db, conn, userinfo['preferred_username'])
if user is not None:
return user
return SimpleKITUser(login_name=userinfo['preferred_username'],
first_name=userinfo.get('givenName', None),
last_name=userinfo.get('sn', None),
email=userinfo['email'])
@login_oic.route('/api/oic_responder')
def oic_responder(t_host=None):
s = request.environ['beaker.session']
oic_client = get_client()
aresp = get_authorization_response(oic_client)
code = aresp["code"]
assert aresp["state"] == s["state"]
args = {
"code": aresp['code'],
"redirect_uri": app.config.get('OIC_REDIR'),
}
resp = oic_client.do_access_token_request(state=aresp['state'],
request_args=args,
authn_method='client_secret_basic')
userinfo = oic_client.do_user_info_request(state=s["state"])
s['login'] = user_from_userinfo(db, get_db_conn(), userinfo)
s.save()
return redirect('/oic_login')
@login_oic.route('/api/debug_oic_responder/<t_host>')
def debug_oic_responder(t_host=None):
if not (db.host_omdl.OP_ENV_IS_DEVEL and t_host is not None and t_host.split(':')[0] == 'localhost'):
abort(404)
oic_client = get_client()
aresp = get_authorization_response(oic_client)
code = aresp["code"]
args = {
"code": aresp['code'],
"redirect_uri": app.config.get('DEBUG_OIC_REDIR') + '/'+t_host,
}
resp = oic_client.do_access_token_request(state=aresp['state'],
request_args=args,
authn_method='client_secret_basic')
print(resp)
userinfo = oic_client.do_user_info_request(state=aresp["state"])
new_target = 'http://'+t_host+'/api/debug_oic_receiver'
return render_template('debug_forward.html', **{'redir':t_host,'new_target': new_target, 'userinfo': userinfo})
@login_oic.route('/api/debug_oic_receiver', methods=['POST'])
def debug_oic_receiver():
if not db.host_omdl.OP_ENV_IS_DEVEL:
abort(404)
s = request.environ['beaker.session']
s['login'] = user_from_userinfo(db, get_db_conn(), request.form)
s.save()
return redirect('http://'+request.form['redir']+'/oic_login')
@login_oic.route('/api/logout', methods=['POST'])
def api_logout():
s = request.environ['beaker.session']
if 'login' in s:
if request.json.get('token_pk', None) is not None:
APIToken(login_name=s['login'].login_name, pk=int(request.json['token_pk'])).delete(db, get_db_conn())
s.delete()
s.save()
return jsonify({'logout': 'success'})
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment