Merge branch 'maennel-ci_testing'

This commit is contained in:
Roland Hedberg 2014-12-16 11:16:46 +01:00
commit 6ee5fb368c
59 changed files with 15119 additions and 5207 deletions

11
.gitignore vendored
View File

@ -9,6 +9,7 @@ Vagrantfile
build
dist
*.egg-info
*.egg
# Compiled files
*.pyc
@ -17,16 +18,18 @@ dist
*.log
*.log.*
# Tox testing
.tox
# Dynamically created doc folders
doc/_build
keys
static
# Remaining stuff
oidc_example/op2/client_db.db
oidc_example/op2/config.py
oidc_example/op2/modules/base.mako.py
oidc_example/op2/modules/login.mako.py
oidc_example/op2/modules/root.mako.py
oidc_example/op2/modules/unauthorized.mako.py
oidc_example/op2/modules
oidc_example/op2/sp.xml
oidc_example/op2/sp_cert/tmp_mycert.pem
oidc_example/op2/sp_cert/tmp_mykey.pem

View File

@ -1,5 +1,5 @@
<%!
def op_choice(op_list):
def op_choice(op_list):
"""
Creates a dropdown list of OpenID Connect providers
"""
@ -13,47 +13,50 @@ def op_choice(op_list):
<!DOCTYPE html>
<html>
<head>
<head>
<title>pyoidc RP</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="static/style.css" rel="stylesheet" media="all">
<link href="static/style.css" rel="stylesheet" media="all">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<![endif]-->
</head>
<body>
</head>
<body>
<!-- Static navbar -->
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<a class="navbar-brand" href="#">pyoidc RP</a>
</div>
<!-- Static navbar -->
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<a class="navbar-brand" href="#">pyoidc RP</a>
</div>
</div>
<div class="container">
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<form class="form-signin" action="rp" method="get">
<h1>OP by UID</h1>
<h3>Chose the OpenID Connect Provider: </h3>
<h1>OP by UID</h1>
<h3>Chose the OpenID Connect Provider: </h3>
<p>From this list</p>
${op_choice(op_list)}
<p> OR by providing your unique identifier at the OP. </p>
<input type="text" id="uid" name="uid" class="form-control" placeholder="UID" autofocus>
<button class="btn btn-lg btn-primary btn-block" type="submit">Start</button>
</form>
</div>
</div>
</div> <!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/static/jquery.min.1.9.1.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</div>
<!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/static/jquery.min.1.9.1.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</body>
</html>

View File

@ -1,53 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<head>
<title>pyoidc RP</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="static/style.css" rel="stylesheet" media="all">
<link href="static/style.css" rel="stylesheet" media="all">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<![endif]-->
</head>
<body>
</head>
<body>
<!-- Static navbar -->
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<!-- Static navbar -->
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">pyoidc RP</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
</button>
<a class="navbar-brand" href="#">pyoidc RP</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="logout">Logout</a></li>
</ul>
</div><!--/.nav-collapse -->
</ul>
</div>
<!--/.nav-collapse -->
</div>
<div class="container">
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>OP result</h1>
<p>You have failed to connect to the designated OP with the message:</p>
<p>${error}</p>
</div>
<div class="container">
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>OP result</h1>
<p>You have failed to connect to the designated OP with the message:</p>
<p>${error}</p>
</div>
</div>
<!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/static/jquery.min.1.9.1.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</div> <!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/static/jquery.min.1.9.1.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</body>
</html>

View File

@ -1,29 +1,29 @@
<!DOCTYPE html>
<%!
import htmlentitydefs
import re, string
<%!
import htmlentitydefs
import re, string
# this pattern matches substrings of reserved and non-ASCII characters
pattern = re.compile(r"[&<>\"\x80-\xff]+")
# this pattern matches substrings of reserved and non-ASCII characters
pattern = re.compile(r"[&<>\"\x80-\xff]+")
# create character map
entity_map = {}
# create character map
entity_map = {}
for i in range(256):
for i in range(256):
entity_map[chr(i)] = "&#%d;" % i
for entity, char in htmlentitydefs.entitydefs.items():
for entity, char in htmlentitydefs.entitydefs.items():
if entity_map.has_key(char):
entity_map[char] = "&%s;" % entity
def escape_entity(m, get=entity_map.get):
def escape_entity(m, get=entity_map.get):
return string.join(map(get, m.group()), "")
def escape(string):
def escape(string):
return pattern.sub(escape_entity, string)
def create_result(userinfo):
def create_result(userinfo):
"""
Creates a display of user information.
"""
@ -35,56 +35,58 @@
element += "<div class='col-md-7'>" + escape(unicode(value).encode("utf-8")) + "</div>"
element += "</div>"
return element
%>
%>
<html>
<head>
<head>
<title>pyoidc RP</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap -->
<link href="static/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="static/style.css" rel="stylesheet" media="all">
<link href="static/style.css" rel="stylesheet" media="all">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<script src="../../assets/js/html5shiv.js"></script>
<script src="../../assets/js/respond.min.js"></script>
<![endif]-->
</head>
<body>
</head>
<body>
<!-- Static navbar -->
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<!-- Static navbar -->
<div class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">pyoidc RP</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="logout">Logout</a></li>
</ul>
</div><!--/.nav-collapse -->
</button>
<a class="navbar-brand" href="#">pyoidc RP</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="logout">Logout</a></li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
<div class="container">
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>OP result</h1>
${create_result(userinfo)}
</div>
</div>
</div> <!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/static/jquery.min.1.9.1.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</div>
<!-- /container -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/static/jquery.min.1.9.1.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
</body>
</body>
</html>

View File

@ -22,7 +22,7 @@ class Client(oic.Client):
def __init__(self, client_id=None, ca_certs=None,
client_prefs=None, client_authn_method=None, keyjar=None,
verify_ssl=True, behaviour=None):
oic.Client.__init__(self, client_id, ca_certs, client_prefs,
super(Client, self).__init__(self, client_id, ca_certs, client_prefs,
client_authn_method, keyjar, verify_ssl)
if behaviour:
self.behaviour = behaviour
@ -191,7 +191,7 @@ class OIDCClients(object):
ProviderConfigurationResponse(**kwargs["provider_info"]),
kwargs["provider_info"]["issuer"])
client.store_registration_info(RegistrationResponse(
**kwargs["client_registration"]))
**kwargs["client_registration"]))
elif _key_set == set(["srv_discovery_url", "client_registration"]):
_ = client.provider_config(kwargs["srv_discovery_url"])
client.store_registration_info(RegistrationResponse(

View File

@ -5,12 +5,12 @@ import urllib
from jwkest.jws import alg2keytype
from mako.lookup import TemplateLookup
from urlparse import parse_qs
import logging
from oic.utils.http_util import NotFound
from oic.utils.http_util import Response
from oic.utils.http_util import Redirect
import logging
LOGGER = logging.getLogger("")
LOGFILE_NAME = 'rp.log'
@ -34,7 +34,7 @@ LOOKUP = TemplateLookup(directories=['templates', 'htdocs'],
SERVER_ENV = {}
#noinspection PyUnresolvedReferences
# noinspection PyUnresolvedReferences
def static(environ, start_response, logger, path):
logger.info("[static]sending: %s" % (path,))
@ -172,6 +172,7 @@ def application(environ, start_response):
return opchoice(environ, start_response, CLIENTS)
if __name__ == '__main__':
from oidc import OIDCClients
from oidc import OIDCError

View File

@ -4,9 +4,9 @@
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
}
.btn-default:active,
@ -21,117 +21,117 @@
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn:active,
.btn.active {
background-image: none;
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%);
background-repeat: repeat-x;
border-color: #e0e0e0;
border-color: #ccc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
text-shadow: 0 1px 0 #fff;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%);
background-repeat: repeat-x;
border-color: #e0e0e0;
border-color: #ccc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
}
.btn-default:active,
.btn-default.active {
background-color: #e6e6e6;
border-color: #e0e0e0;
background-color: #e6e6e6;
border-color: #e0e0e0;
}
.btn-primary {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
border-color: #2d6ca2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
border-color: #2d6ca2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
}
.btn-primary:active,
.btn-primary.active {
background-color: #3071a9;
border-color: #2d6ca2;
background-color: #3071a9;
border-color: #2d6ca2;
}
.btn-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
border-color: #419641;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
border-color: #419641;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
}
.btn-success:active,
.btn-success.active {
background-color: #449d44;
border-color: #419641;
background-color: #449d44;
border-color: #419641;
}
.btn-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
border-color: #eb9316;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
border-color: #eb9316;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
}
.btn-warning:active,
.btn-warning.active {
background-color: #ec971f;
border-color: #eb9316;
background-color: #ec971f;
border-color: #eb9316;
}
.btn-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
border-color: #c12e2a;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
border-color: #c12e2a;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
}
.btn-danger:active,
.btn-danger.active {
background-color: #c9302c;
border-color: #c12e2a;
background-color: #c9302c;
border-color: #c12e2a;
}
.btn-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
border-color: #2aabd2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
border-color: #2aabd2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
}
.btn-info:active,
.btn-info.active {
background-color: #31b0d5;
border-color: #2aabd2;
background-color: #31b0d5;
border-color: #2aabd2;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.dropdown-menu > li > a:hover,
@ -139,246 +139,246 @@
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #357ebd;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
background-color: #357ebd;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
}
.navbar {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
background-repeat: repeat-x;
border-radius: 4px;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
background-repeat: repeat-x;
border-radius: 4px;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
}
.navbar .navbar-nav > .active > a {
background-color: #f8f8f8;
background-color: #f8f8f8;
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}
.navbar-inverse {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222));
background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%);
background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%);
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222));
background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%);
background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%);
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
}
.navbar-inverse .navbar-nav > .active > a {
background-color: #222222;
background-color: #222222;
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
border-radius: 0;
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.alert-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
background-repeat: repeat-x;
border-color: #b2dba1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
background-repeat: repeat-x;
border-color: #b2dba1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
}
.alert-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
background-repeat: repeat-x;
border-color: #9acfea;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
background-repeat: repeat-x;
border-color: #9acfea;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
}
.alert-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
background-repeat: repeat-x;
border-color: #f5e79e;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
background-repeat: repeat-x;
border-color: #f5e79e;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
}
.alert-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
background-repeat: repeat-x;
border-color: #dca7a7;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
background-repeat: repeat-x;
border-color: #dca7a7;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
}
.progress {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
}
.progress-bar {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
}
.progress-bar-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
}
.progress-bar-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
}
.progress-bar-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
}
.progress-bar-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #3071a9;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
background-repeat: repeat-x;
border-color: #3278b3;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
text-shadow: 0 -1px 0 #3071a9;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
background-repeat: repeat-x;
border-color: #3278b3;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.panel-default > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8));
background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%);
background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8));
background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%);
background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
}
.panel-primary > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
}
.panel-success > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
}
.panel-info > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
}
.panel-warning > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
}
.panel-danger > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
}
.well {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
background-repeat: repeat-x;
border-color: #dcdcdc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
background-repeat: repeat-x;
border-color: #dcdcdc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
body {
min-height: 2000px;
padding-top: 70px;
min-height: 2000px;
padding-top: 70px;
}

View File

@ -31,8 +31,8 @@ DEFAULT_POST_CONTENT_TYPE = URL_ENCODED
REQUEST2ENDPOINT = {
"AuthorizationRequest": "authorization_endpoint",
"AccessTokenRequest": "token_endpoint",
# ROPCAccessTokenRequest: "authorization_endpoint",
# CCAccessTokenRequest: "authorization_endpoint",
# ROPCAccessTokenRequest: "authorization_endpoint",
# CCAccessTokenRequest: "authorization_endpoint",
"RefreshAccessTokenRequest": "token_endpoint",
"TokenRevocationRequest": "token_endpoint"}
@ -86,6 +86,7 @@ def rndstr(size=16):
class ExpiredToken(PyoidcError):
pass
# -----------------------------------------------------------------------------
@ -272,7 +273,7 @@ class PBase(object):
self.keyjar = KeyJar(verify_ssl=verify_ssl)
self.request_args = {"allow_redirects": False}
#self.cookies = {}
# self.cookies = {}
self.cookiejar = cookielib.FileCookieJar()
self.ca_certs = ca_certs
if ca_certs:
@ -350,12 +351,12 @@ class PBase(object):
std_attr["version"] = std_attr["version"].split(",")[0]
except (TypeError, AttributeError):
pass
new_cookie = cookielib.Cookie(**std_attr)
self.cookiejar.set_cookie(new_cookie)
#return cookiejar
# return cookiejar
def http_request(self, url, method="GET", **kwargs):
_kwargs = copy.copy(self.request_args)
@ -371,14 +372,14 @@ class PBase(object):
except Exception as err:
logger.error(
"http_request failed: %s, url: %s, htargs: %s, method: %s" % (
err, url, _kwargs, method))
err, url, _kwargs, method))
raise
try:
set_cookie = r.headers["set-cookie"]
# Telekom fix
# set_cookie = set_cookie.replace(
# "=;Path=/;Expires=Thu, 01-Jan-1970 00:00:01 GMT;HttpOnly,", "")
# "=;Path=/;Expires=Thu, 01-Jan-1970 00:00:01 GMT;HttpOnly,", "")
logger.debug("RECEIVED COOKIEs: %s" % set_cookie)
self.set_cookie(SimpleCookie(set_cookie))
except (AttributeError, KeyError), err:
@ -421,9 +422,9 @@ class Client(PBase):
self.client_authn_method = client_authn_method
self.keyjar = keyjar or KeyJar(verify_ssl=verify_ssl)
self.verify_ssl = verify_ssl
#self.secret_type = "basic "
# self.secret_type = "basic "
#self.state = None
# self.state = None
self.nonce = None
self.grant = {}
@ -463,7 +464,7 @@ class Client(PBase):
client_secret = property(get_client_secret, set_client_secret)
def reset(self):
#self.state = None
# self.state = None
self.nonce = None
self.grant = {}
@ -518,8 +519,8 @@ class Client(PBase):
def get_grant(self, state, **kwargs):
# try:
# _state = kwargs["state"]
# if not _state:
# _state = kwargs["state"]
# if not _state:
# _state = self.state
# except KeyError:
# _state = self.state
@ -553,19 +554,19 @@ class Client(PBase):
elif token.is_valid():
return token
else:
raise ExpiredToken()
raise ExpiredToken("Token has expired")
def construct_request(self, request, request_args=None, extra_args=None):
if request_args is None:
request_args = {}
#logger.debug("request_args: %s" % request_args)
# logger.debug("request_args: %s" % request_args)
kwargs = self._parse_args(request, **request_args)
if extra_args:
kwargs.update(extra_args)
#logger.debug("kwargs: %s" % kwargs)
#logger.debug("request: %s" % request)
# logger.debug("kwargs: %s" % kwargs)
# logger.debug("request: %s" % request)
return request(**kwargs)
def construct_Message(self, request=Message, request_args=None,
@ -573,7 +574,7 @@ class Client(PBase):
return self.construct_request(request, request_args, extra_args)
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def construct_AuthorizationRequest(self, request=AuthorizationRequest,
request_args=None, extra_args=None,
**kwargs):
@ -595,7 +596,7 @@ class Client(PBase):
return self.construct_request(request, request_args, extra_args)
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def construct_AccessTokenRequest(self,
request=AccessTokenRequest,
request_args=None, extra_args=None,
@ -689,7 +690,7 @@ class Client(PBase):
header_ext = {"Content-type": content_type}
if accept:
header_ext = {"Accept": accept}
if "headers" in kwargs.keys():
kwargs["headers"].update(header_ext)
else:
@ -804,7 +805,7 @@ class Client(PBase):
if not verf:
raise PyoidcError("Verification of the response failed")
if resp.type() == "AuthorizationResponse" and \
"scope" not in resp:
"scope" not in resp:
try:
resp["scope"] = kwargs["scope"]
except KeyError:
@ -1111,14 +1112,14 @@ class Server(PBase):
if not keyjar:
keyjar = self.keyjar
#areq = message().from_(txt, keys, verify)
# areq = message().from_(txt, keys, verify)
areq = request().deserialize(txt, "jwt", keyjar=keyjar,
verify=verify)
areq.verify()
return areq
def parse_body_request(self, request=AccessTokenRequest, body=None):
#req = message(reqmsg).from_urlencoded(body)
# req = message(reqmsg).from_urlencoded(body)
req = request().deserialize(body, "urlencoded")
req.verify()
return req

View File

@ -2,7 +2,6 @@
__author__ = 'rohe0002'
import time
from hashlib import md5
from oic.utils import http_util
@ -11,6 +10,7 @@ from oic.oauth2 import Grant
from oic.oauth2 import rndstr
from oic.oauth2.message import *
ENDPOINTS = ["authorization_endpoint", "token_endpoint", "userinfo_endpoint",
"check_id_endpoint", "registration_endpoint",
"token_revokation_endpoint"]
@ -77,7 +77,7 @@ class Consumer(Client):
""" An OAuth2 consumer implementation
"""
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def __init__(self, session_db, client_config=None,
server_info=None, authz_page="", response_type="",
scope="", flow_type="", password=None):
@ -168,7 +168,7 @@ class Consumer(Client):
self.sdb[sid] = res
#noinspection PyUnusedLocal,PyArgumentEqualDefault
# noinspection PyUnusedLocal,PyArgumentEqualDefault
def begin(self, baseurl, request, response_type="", **kwargs):
""" Begin the OAuth2 flow

View File

@ -1,15 +1,15 @@
import logging
import urllib
import urlparse
import requests
from oic.oic import OIDCONF_PATTERN
from oic.oic.message import ProviderConfigurationResponse, AuthorizationResponse
import requests
from oic.utils.keyio import KeyJar
from oic.utils.time_util import utc_time_sans_frac
from oic.oic.provider import secret
from oic.oic.provider import RegistrationEndpoint
from oic.oic.provider import Endpoint
from oic import oauth2
from oic.oauth2 import provider
from oic.oauth2 import VerificationError
@ -27,13 +27,13 @@ from oic.oauth2 import SINGLE_OPTIONAL_INT
from oic.exception import UnknownAssertionType
from oic.exception import PyoidcError
from oic.exception import AuthzError
from oic.utils.authn.client import AuthnFailure
from oic.utils.http_util import Unauthorized, NoContent
from oic.utils.http_util import Response
from oic.utils.http_util import BadRequest
from oic.utils.http_util import Forbidden
logger = logging.getLogger(__name__)
__author__ = 'roland'
@ -180,8 +180,8 @@ class Provider(provider.Provider):
# @staticmethod
# def _uris_to_dict(uris):
# ruri = {}
# for uri in uris:
# ruri = {}
# for uri in uris:
# base, query = urllib.splitquery(uri)
# if query:
# try:
@ -211,7 +211,7 @@ class Provider(provider.Provider):
if query:
tup.append((base, query))
else:
tup.append((base,""))
tup.append((base, ""))
return tup
@staticmethod
@ -242,7 +242,7 @@ class Provider(provider.Provider):
_cinfo["client_secret"] = secret(self.seed, _id)
_cinfo["client_id_issued_at"] = utc_time_sans_frac()
_cinfo["client_secret_expires_at"] = utc_time_sans_frac() + \
self.secret_lifetime
self.secret_lifetime
# If I support client info endpoint
if ClientInfoEndpoint in self.endp:
@ -289,7 +289,7 @@ class Provider(provider.Provider):
for key in _cinfo.keys():
if key in ["client_id_issued_at", "client_secret_expires_at",
"registration_access_token","registration_client_uri"]:
"registration_access_token", "registration_client_uri"]:
continue
if key not in request:
del _cinfo[key]
@ -352,7 +352,7 @@ class Provider(provider.Provider):
return self.client_info(client_id)
def client_info_endpoint(self, request, environ,
method="GET", query="", **kwargs):
method="GET", query="", **kwargs):
"""
Operations on this endpoint are switched through the use of different
HTTP methods

View File

@ -3,15 +3,16 @@ import logging
import urllib
import urlparse
import json
from jwkest import b64d
import jwkest
from jwkest.jwe import JWE
from jwkest.jwk import keyitems2keyreps
from jwkest.jws import JWS
from oic.exception import PyoidcError
from oic.exception import MessageException
logger = logging.getLogger(__name__)
@ -116,7 +117,8 @@ class Message(object):
if not self.lax:
for attribute, (_, req, _ser, _, na) in _spec.items():
if req and attribute not in self._dict:
raise MissingRequiredAttribute("%s" % attribute, self)
raise MissingRequiredAttribute("%s" % attribute,
"%s" % self)
params = []
@ -149,7 +151,7 @@ class Message(object):
elif isinstance(val, Message):
try:
params.append((key, str(_ser(val, sformat="urlencoded",
lev=lev))))
lev=lev))))
except TypeError:
params.append((key, val))
elif val is None:
@ -191,8 +193,8 @@ class Message(object):
:return: An instance of the cls class
"""
#parse_qs returns a dictionary with keys and values. The values are
#always lists even if there is only one value in the list.
# parse_qs returns a dictionary with keys and values. The values are
# always lists even if there is only one value in the list.
#keys only appears once.
if isinstance(urlencoded, basestring):
@ -327,8 +329,8 @@ class Message(object):
return self
def _add_value(self, skey, vtyp, key, val, _deser, null_allowed):
# if not val:
# return
# if not val:
# return
if isinstance(val, list):
if (len(val) == 0 or val[0] is None) and null_allowed is False:
@ -529,14 +531,14 @@ class Message(object):
raise ValueError("Not allowed value '%s'" % val)
elif isinstance(typ, list):
if isinstance(val, list):
#_typ = typ[0]
# _typ = typ[0]
for item in val:
if item not in _allowed:
raise ValueError("Not allowed value '%s'" % val)
elif val is None and na is False:
raise ValueError("Not allowed value '%s'" % val)
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def verify(self, **kwargs):
"""
Make sure all the required values are there and that the values are
@ -628,8 +630,8 @@ class Message(object):
return True
# def __getattr__(self, item):
# return self._dict[item]
# def __getattr__(self, item):
# return self._dict[item]
def __delitem__(self, key):
del self._dict[key]
@ -674,7 +676,8 @@ class Message(object):
return self.from_json(_res[0])
def copy(self):
return copy.deepcopy(self)
return copy.deepcopy(self)
# =============================================================================
@ -688,10 +691,11 @@ def add_non_standard(msg1, msg2):
if key not in msg1.c_param:
msg1[key] = val
# =============================================================================
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def list_serializer(vals, sformat="urlencoded", lev=0):
if isinstance(vals, basestring) or not isinstance(vals, list):
raise ValueError("Expected list: %s" % vals)
@ -701,7 +705,7 @@ def list_serializer(vals, sformat="urlencoded", lev=0):
return vals
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def list_deserializer(val, sformat="urlencoded"):
if sformat == "urlencoded":
if isinstance(val, basestring):
@ -739,6 +743,7 @@ def json_serializer(obj, sformat="urlencoded", lev=0):
def json_deserializer(txt, sformat="urlencoded"):
return json.loads(txt)
VTYPE = 0
VREQUIRED = 1
VSER = 2
@ -873,6 +878,7 @@ class TokenRevocationRequest(Message):
class ResourceRequest(Message):
c_param = {"access_token": SINGLE_OPTIONAL_STRING}
MSG = {
"Message": Message,
"ErrorResponse": ErrorResponse,
@ -897,6 +903,7 @@ def factory(msgtype):
except KeyError:
raise Exception("Unknown message type: %s" % msgtype)
if __name__ == "__main__":
foo = AccessTokenRequest(grant_type="authorization_code",
code="foo",

View File

@ -5,6 +5,7 @@ import urllib
import urlparse
from oic.utils.sdb import AccessCodeUsed, AuthnEvent
__author__ = 'rohe0002'
import base64
@ -94,7 +95,7 @@ def token_response(**kwargs):
return aresp
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def none_response(**kwargs):
_areq = kwargs["areq"]
aresp = NoneResponse()
@ -372,7 +373,7 @@ class Provider(object):
try:
if len(self.authn_broker) == 1:
return self.authn_broker[0]
return self.authn_broker[0]
else:
try:
_values = areq["acr_values"]
@ -388,7 +389,7 @@ class Provider(object):
for _acr in _values:
res = self.authn_broker.pick(_acr, comparision_type)
if res:
#Return the best guess by pick.
# Return the best guess by pick.
return res[0]
except KeyError:
pass
@ -534,11 +535,11 @@ class Provider(object):
pass
if "response_type" in areq and \
len(areq["response_type"]) == 1 and \
"none" in areq["response_type"]:
len(areq["response_type"]) == 1 and \
"none" in areq["response_type"]:
pass
else:
#if self.sdb.is_revoked(sinfo):
# if self.sdb.is_revoked(sinfo):
# return self._error(error="access_denied",
# descr="Token is revoked")
@ -582,7 +583,7 @@ class Provider(object):
except (RedirectURIError, ParameterError), err:
return BadRequest("%s" % err)
#self.sdb.store_session(skey)
# self.sdb.store_session(skey)
# so everything went well should set a SSO cookie
headers = [authn.create_cookie(user, typ="sso", ttl=self.sso_ttl)]
@ -593,7 +594,7 @@ class Provider(object):
def token_scope_check(self, areq, info):
""" Not implemented here """
# if not self.subset(areq["scope"], _info["scope"]):
# LOG_INFO("Asked for scope which is not subset of previous defined")
# LOG_INFO("Asked for scope which is not subset of previous defined")
# err = TokenErrorResponse(error="invalid_scope")
# return Response(err.to_json(), content="application/json")
return None
@ -649,9 +650,8 @@ class Provider(object):
return Response(err.to_json(), content="application/json",
status="401 Unauthorized")
LOG_DEBUG("_tinfo: %s" % _tinfo)
atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo))
LOG_DEBUG("AccessTokenResponse: %s" % atr)

View File

@ -1,6 +1,8 @@
from jwkest.jwe import JWE
from oic.utils.keyio import KeyJar
__author__ = 'rohe0002'
import urlparse
@ -165,7 +167,7 @@ def make_openid_request(arq, keys=None, userinfo_claims=None,
c_args["userinfo"] = Claims(**userinfo_claims)
if idtoken_claims is not None:
#IdTokenClaims
# IdTokenClaims
c_args["id_token"] = Claims(**idtoken_claims)
if c_args:
@ -196,7 +198,7 @@ class Grant(oauth2.Grant):
PREFERENCE2PROVIDER = {
#"require_signed_request_object": "request_object_algs_supported",
# "require_signed_request_object": "request_object_algs_supported",
"request_object_signing_alg": "request_object_signing_alg_values_supported",
"request_object_encryption_alg":
"request_object_encryption_alg_values_supported",
@ -213,7 +215,7 @@ PREFERENCE2PROVIDER = {
"id_token_encrypted_response_enc":
"id_token_encryption_enc_values_supported",
"default_acr_values": "acr_values_supported",
#"require_auth_time":"",
# "require_auth_time":"",
"subject_type": "subject_types_supported",
"token_endpoint_auth_method": "token_endpoint_auth_methods_supported",
"token_endpoint_auth_signing_alg":
@ -222,7 +224,7 @@ PREFERENCE2PROVIDER = {
#"request_object_signing_alg": "request_object_signing_alg_values_supported
}
PROVIDER2PREFERENCE = dict([(v,k) for k,v in PREFERENCE2PROVIDER.items()])
PROVIDER2PREFERENCE = dict([(v, k) for k, v in PREFERENCE2PROVIDER.items()])
PROVIDER_DEFAULT = {
"token_endpoint_auth_method": "client_secret_basic",
@ -230,7 +232,7 @@ PROVIDER_DEFAULT = {
}
#noinspection PyMethodOverriding
# noinspection PyMethodOverriding
class Client(oauth2.Client):
_endpoints = ENDPOINTS
@ -263,7 +265,7 @@ class Client(oauth2.Client):
self.behaviour = {
"request_object_signing_alg":
DEF_SIGN_ALG["openid_request_object"]}
DEF_SIGN_ALG["openid_request_object"]}
self.wf = WebFinger(OIC_ISSUER)
self.wf.httpd = self
@ -336,7 +338,7 @@ class Client(oauth2.Client):
if request_args is not None:
# if "claims" in request_args:
# kwargs["claims"] = request_args["claims"]
# kwargs["claims"] = request_args["claims"]
# del request_args["claims"]
if "nonce" not in request_args:
_rt = request_args["response_type"]
@ -400,7 +402,7 @@ class Client(oauth2.Client):
return areq
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def construct_AccessTokenRequest(self, request=AccessTokenRequest,
request_args=None, extra_args=None,
**kwargs):
@ -1150,7 +1152,7 @@ class Client(oauth2.Client):
return ""
#noinspection PyMethodOverriding
# noinspection PyMethodOverriding
class Server(oauth2.Server):
def __init__(self, keyjar=None, ca_certs=None, verify_ssl=True):
oauth2.Server.__init__(self, keyjar, ca_certs, verify_ssl)
@ -1198,7 +1200,7 @@ class Server(oauth2.Server):
"""
param = self._parse_urlencoded(url, query)
assert "access_token" in param # ignore the rest
assert "access_token" in param # ignore the rest
return deser_id_token(self, param["access_token"][0])
def _parse_request(self, request, data, sformat, client_id=None):

View File

@ -25,8 +25,8 @@ from oic.utils.http_util import Response
from oic.utils.authn.client import bearer_auth
# Used in claims.py
#from oic.oic.message import RegistrationRequest
#from oic.oic.message import RegistrationResponse
# from oic.oic.message import RegistrationRequest
# from oic.oic.message import RegistrationResponse
logger = logging.getLogger(__name__)
@ -44,6 +44,7 @@ class UserClaimsResponse(Message):
"endpoint": SINGLE_OPTIONAL_STRING,
"access_token": SINGLE_OPTIONAL_STRING}
# def verify(self, **kwargs):
# if "jwt" in self:
# # Try to decode the JWT, checks the signature
@ -65,7 +66,6 @@ class UserInfoClaimsRequest(Message):
class OICCServer(OicServer):
def parse_user_claims_request(self, info, sformat="urlencoded"):
return self._parse_request(UserClaimsRequest, info, sformat)
@ -74,7 +74,6 @@ class OICCServer(OicServer):
class ClaimsServer(Provider):
def __init__(self, name, sdb, cdb, userinfo, client_authn, urlmap=None,
ca_certs="", keyjar=None, hostname="", dist_claims_mode=None):
Provider.__init__(self, name, sdb, cdb, None, userinfo, None,
@ -176,7 +175,6 @@ class ClaimsServer(Provider):
class ClaimsClient(Client):
def __init__(self, client_id=None, ca_certs=""):
Client.__init__(self, client_id, ca_certs)
@ -208,8 +206,8 @@ class ClaimsClient(Client):
else:
http_args.update(http_args)
# http_args = self.init_authentication_method(csi, "bearer_header",
# request_args)
# http_args = self.init_authentication_method(csi, "bearer_header",
# request_args)
return self.request_and_return(url, request_resp, method, body,
body_type, extended=False,

View File

@ -94,6 +94,7 @@ def clean_response(aresp):
return atr
IGNORE = ["request2endpoint", "response2error", "grant_class", "token_class"]
CONSUMER_PREF_ARGS = [
@ -121,7 +122,7 @@ class Consumer(Client):
""" An OpenID Connect consumer implementation
"""
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
def __init__(self, session_db, config, client_config=None,
server_info=None, debug=False, client_prefs=None):
""" Initializes a Consumer instance.
@ -198,7 +199,7 @@ class Consumer(Client):
"""
self.sdb[sid] = self.dictionary()
#noinspection PyUnusedLocal,PyArgumentEqualDefault
# noinspection PyUnusedLocal,PyArgumentEqualDefault
def begin(self, scope="", response_type="", use_nonce=False, path="",
**kwargs):
""" Begin the OIDC flow
@ -326,7 +327,7 @@ class Consumer(Client):
return http_util.BadRequest("Missing query")
_log_info("response: %s" % query)
if "code" in self.config["response_type"]:
# Might be an error response
_log_info("Expect Authorization Response")
@ -410,7 +411,7 @@ class Consumer(Client):
def refresh_token(self):
pass
#noinspection PyUnusedLocal
def get_user_info(self, state):
uinfo = self.do_user_info_request(state=state, schema="openid")

View File

@ -64,7 +64,7 @@ def encrypt(key, msg, iv=None, alg="aes_128_cbc", padding="PKCS#7",
if _block_size:
plen = _block_size - (len(msg) % _block_size)
c = chr(plen)
msg += c*plen
msg += c * plen
cipher, iv = build_cipher(key, iv, alg)
cmsg = iv + cipher.encrypt(msg)
@ -95,6 +95,7 @@ def decrypt(key, msg, iv=None, padding="PKCS#7", b64dec=True):
res = res[:-ord(res[-1])]
return res
if __name__ == "__main__":
key_ = "1234523451234545" # 16 byte key
# Iff padded the message doesn't have to be multiple of 16 in length

View File

@ -77,7 +77,7 @@ class AuthnBroker(object):
if level and level != item["level"]:
_remain.append(_ref)
if authn_authority and \
authn_authority != item["authn_authority"]:
authn_authority != item["authn_authority"]:
_remain.append(_ref)
if _remain:
self.db[acr] = _remain
@ -204,6 +204,7 @@ def make_auth_verify(callback, next_module_instance=None):
setup_multi_auth (in multi_auth.py)
:return: function encapsulating the specified callback which properly handles a multi auth chain.
"""
def auth_verify(environ, start_response, logger):
kwargs = extract_from_request(environ)

View File

@ -3,6 +3,7 @@ import base64
from jwkest import Invalid
from jwkest import MissingKey
from jwkest.jws import alg2keytype
from oic.exception import UnknownAssertionType
from oic.exception import NotForMe
from oic.oauth2 import rndstr, VREQUIRED
@ -65,6 +66,7 @@ class ClientSecretBasic(ClientAuthnMethod):
Server, authenticate with the Authorization Server in accordance with
Section 3.2.1 of OAuth 2.0 [RFC6749] using HTTP Basic authentication scheme.
"""
def construct(self, cis, request_args=None, http_args=None, **kwargs):
"""
:param cis: Request class instance
@ -125,6 +127,7 @@ class ClientSecretPost(ClientSecretBasic):
Section 3.2.1 of OAuth 2.0 [RFC6749] by including the Client Credentials in
the request body.
"""
def construct(self, cis, request_args=None, http_args=None, **kwargs):
if "client_secret" not in cis:
try:
@ -177,7 +180,7 @@ class BearerHeader(ClientAuthnMethod):
_acc_token = request_args["access_token"]
# Do I need to base64 encode the access token ? Probably !
#_bearer = "Bearer %s" % base64.b64encode(_acc_token)
# _bearer = "Bearer %s" % base64.b64encode(_acc_token)
_bearer = "Bearer %s" % _acc_token
if http_args is None:
http_args = {"headers": {}}
@ -246,7 +249,6 @@ def bearer_auth(req, authn):
class JWSAuthnMethod(ClientAuthnMethod):
def choose_algorithm(self, entity, **kwargs):
try:
algorithm = kwargs["algorithm"]
@ -325,7 +327,7 @@ class JWSAuthnMethod(ClientAuthnMethod):
return False
logger.debug("authntoken: %s" % bjwt.to_dict())
#logger.debug("known clients: %s" % self.cli.cdb.keys())
# logger.debug("known clients: %s" % self.cli.cdb.keys())
try:
cid = kwargs["client_id"]
except KeyError:
@ -361,6 +363,7 @@ class ClientSecretJWT(JWSAuthnMethod):
The HMAC (Hash-based Message Authentication Code) is calculated using the
bytes of the UTF-8 representation of the client_secret as the shared key.
"""
def choose_algorithm(self, entity="client_secret_jwt", **kwargs):
return JWSAuthnMethod.choose_algorithm(self, entity, **kwargs)
@ -373,6 +376,7 @@ class PrivateKeyJWT(JWSAuthnMethod):
"""
Clients that have registered a public key sign a JWT using that key.
"""
def choose_algorithm(self, entity="private_key_jwt", **kwargs):
return JWSAuthnMethod.choose_algorithm(self, entity, **kwargs)
@ -381,7 +385,7 @@ class PrivateKeyJWT(JWSAuthnMethod):
alg=algorithm)
#from oic.utils.authn.client_saml import SAML2_BEARER_ASSERTION_TYPE
# from oic.utils.authn.client_saml import SAML2_BEARER_ASSERTION_TYPE
CLIENT_AUTHN_METHOD = {

View File

@ -1,7 +1,9 @@
import base64
from oic.utils.authn.client import ClientAuthnMethod
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
__author__ = 'rolandh'
SAML2_BEARER_ASSERTION_TYPE = \
@ -16,6 +18,7 @@ else:
"""
Authenticating clients using the SAML2 assertion profile
"""
def construct(self, cis, assertion=None, **kwargs):
"""
@ -38,8 +41,8 @@ else:
def _verify_saml2_assertion(self, assertion):
subject = assertion.subject
#client_id = subject.name_id.text
#who_ever_issued_it = assertion.issuer.text
# client_id = subject.name_id.text
# who_ever_issued_it = assertion.issuer.text
audience = []
for ar in subject.audience_restiction:

View File

@ -1,10 +1,13 @@
import urlparse
from urlparse import parse_qs
from oic.utils.authn.user import UserAuthnMethod, logger, UsernamePasswordMako
from oic.utils.http_util import Response, Unauthorized, Redirect
from oic.utils.authn.user import logger, UsernamePasswordMako
from oic.utils.http_util import Unauthorized, Redirect
__author__ = 'danielevertsson'
class JavascriptFormMako(UsernamePasswordMako):
"""Do user authentication using the normal username password form in a
WSGI environment using Mako as template system"""

View File

@ -1,13 +1,14 @@
import logging
from oic.utils.userinfo.ldap_info import UserInfoLDAP
__author__ = 'haho0032'
logger = logging.getLogger(__name__)
class UserLDAPMemberValidation(UserInfoLDAP):
def __init__(self, verify_attr=None, verify_attr_valid=None, **kwargs):
UserInfoLDAP.__init__(self, **kwargs)
self.verify_attr = verify_attr

View File

@ -1,6 +1,8 @@
import ldap
from oic.utils.authn.user import UsernamePasswordMako
SCOPE_MAP = {
"base": ldap.SCOPE_BASE,
"onelevel": ldap.SCOPE_ONELEVEL,

View File

@ -9,6 +9,7 @@ class MultiAuthnMethod(UserAuthnMethod):
Small auth module just to kick off multi auth chains (it must be the first module in the chain).
Do no instantiate this object, use setup_multi_auth instead!
"""
def __init__(self, auth_module):
UserAuthnMethod.__init__(self, None)
self.auth_module = auth_module
@ -49,6 +50,7 @@ class AuthnIndexedEndpointWrapper(UserAuthnMethod):
Wrapper class for using an authn module with multiple endpoints.
Encapsulates the desired index of the endpoint.
"""
def __init__(self, authn_instance, end_point_index):
UserAuthnMethod.__init__(self, None)

View File

@ -4,21 +4,24 @@ from tempfile import NamedTemporaryFile
from urllib import urlencode
import logging
import base64
from urlparse import parse_qs
from oic.oauth2 import VerificationError
from oic.utils.authn.user import UserAuthnMethod
from oic.utils.authn.user import create_return_url
from urlparse import parse_qs
from oic.utils.http_util import Redirect
from oic.utils.http_util import SeeOther
from oic.utils.http_util import Response
from oic.utils.http_util import Unauthorized
logger = logging.getLogger(__name__)
class ServiceErrorException(Exception):
pass
try:
import saml2
except ImportError:
@ -36,7 +39,7 @@ else:
from saml2.s_utils import UnknownPrincipal
from saml2.s_utils import UnsupportedBinding
#This class handles user authentication with CAS.
# This class handles user authentication with CAS.
class SAMLAuthnMethod(UserAuthnMethod):
CONST_QUERY = "query"
CONST_SAML_COOKIE = "samlauthc"
@ -66,7 +69,7 @@ else:
else:
self.bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST,
BINDING_HTTP_ARTIFACT]
#TODO Why does this exist?
# TODO Why does this exist?
self.verification_endpoint = ""
#Configurations for the SP handler. (pyOpSamlProxy.client.sp.conf)
self.sp_conf = importlib.import_module(spconf)
@ -180,7 +183,7 @@ else:
if not allowed:
return Unauthorized(self.not_authorized), False
#logger.info("parsed OK")'
# logger.info("parsed OK")'
uid = response.assertion.subject.name_id.text
if self.userinfo == "AA":
if response.entity_id is not None and self.samlcache is not None:
@ -333,7 +336,7 @@ else:
_sid = req_id
_rstate = rndstr()
#self.cache.relay_state[_rstate] = came_from
# self.cache.relay_state[_rstate] = came_from
ht_args = _cli.apply_binding(binding, msg_str, destination,
relay_state=_rstate)
@ -348,22 +351,22 @@ else:
return self.response(binding, ht_args, query)
def response(self, binding, http_args, query):
cookie = self.create_cookie(
'{"' + self.CONST_QUERY + '": "' + base64.b64encode(query) +
'" , "' + self.CONST_HASIDP + '": "True" }',
self.CONST_SAML_COOKIE, self.CONST_SAML_COOKIE)
if binding == BINDING_HTTP_ARTIFACT:
resp = Redirect()
elif binding == BINDING_HTTP_REDIRECT:
for param, value in http_args["headers"]:
if param == "Location":
resp = SeeOther(str(value), headers=[cookie])
break
else:
raise ServiceErrorException("Parameter error")
cookie = self.create_cookie(
'{"' + self.CONST_QUERY + '": "' + base64.b64encode(query) +
'" , "' + self.CONST_HASIDP + '": "True" }',
self.CONST_SAML_COOKIE, self.CONST_SAML_COOKIE)
if binding == BINDING_HTTP_ARTIFACT:
resp = Redirect()
elif binding == BINDING_HTTP_REDIRECT:
for param, value in http_args["headers"]:
if param == "Location":
resp = SeeOther(str(value), headers=[cookie])
break
else:
http_args["headers"].append(cookie)
resp = Response(http_args["data"],
headers=http_args["headers"])
raise ServiceErrorException("Parameter error")
else:
http_args["headers"].append(cookie)
resp = Response(http_args["data"],
headers=http_args["headers"])
return resp
return resp

View File

@ -6,17 +6,19 @@ import logging
import requests
import base64
import xml.etree.ElementTree as ET
from oic.utils.authn.user import UserAuthnMethod
from urlparse import parse_qs
from oic.utils.authn.user import UserAuthnMethod
from oic.utils.http_util import Redirect
from oic.utils.http_util import Unauthorized
logger = logging.getLogger(__name__)
#This class handles user authentication with CAS.
# This class handles user authentication with CAS.
class CasAuthnMethod(UserAuthnMethod):
#Standard login url for a CAS server.
# Standard login url for a CAS server.
CONST_CASLOGIN = "/cas/login?"
#Standard URL for validation of a ticket for a CAS server.
CONST_CAS_VERIFY_TICKET = "/serviceValidate"
@ -122,7 +124,7 @@ class CasAuthnMethod(UserAuthnMethod):
if acr is None:
acr = ""
return self.service_url + "?" + self.CONST_NONCE + "=" + nonce + \
"&acr_values=" + acr
"&acr_values=" + acr
def verify(self, request, cookie, **kwargs):
"""

View File

@ -1,8 +1,10 @@
import logging
import time
from oic.utils.http_util import CookieDealer
from oic.utils.authn.user import ToOld
logger = logging.getLogger(__name__)

View File

@ -1,7 +1,7 @@
__author__ = 'rolandh'
#noinspection PyUnusedLocal
# noinspection PyUnusedLocal
class ClaimsMode(object):
def __init__(self, user2mode):
self.user2mode = user2mode

View File

@ -6,8 +6,8 @@ import cgi
import time
import hashlib
import hmac
from urllib import quote
from Cookie import SimpleCookie
from oic.oauth2 import rndstr
from oic.exception import UnsupportedMethod
@ -77,8 +77,8 @@ class NoContent(Response):
class Redirect(Response):
_template = '<html>\n<head><title>Redirecting to %s</title></head>\n' \
'<body>\nYou are being redirected to <a href="%s">%s</a>\n' \
'</body>\n</html>'
'<body>\nYou are being redirected to <a href="%s">%s</a>\n' \
'</body>\n</html>'
_status = '302 Found'
def __call__(self, environ, start_response, **kwargs):
@ -90,8 +90,8 @@ class Redirect(Response):
class SeeOther(Response):
_template = '<html>\n<head><title>Redirecting to %s</title></head>\n' \
'<body>\nYou are being redirected to <a href="%s">%s</a>\n' \
'</body>\n</html>'
'<body>\nYou are being redirected to <a href="%s">%s</a>\n' \
'</body>\n</html>'
_status = '303 See Other'
def __call__(self, environ, start_response, **kwargs):
@ -220,7 +220,7 @@ def cookie_signature(seed, *parts):
return sha1.hexdigest()
def make_cookie(name, load, seed, expire=0, domain="", path="", timestamp=""):
def make_cookie(name, load, seed, expire=0, domain="", path="", timestamp=""):
"""
Create and return a cookie
@ -314,7 +314,10 @@ def get_or_post(environ):
return data
def extract_from_request(environ, kwargs={}):
def extract_from_request(environ, kwargs=None):
if kwargs is None:
kwargs = {}
request = None
try:
request = environ["QUERY_STRING"]
@ -360,7 +363,6 @@ def wsgi_wrapper(environ, start_response, func, **kwargs):
class CookieDealer(object):
def getServer(self):
return self._srv

View File

@ -4,6 +4,7 @@ from Crypto.PublicKey import RSA
from cryptlib.ecc import NISTEllipticCurve
from oic.exception import MessageException
__author__ = 'rohe0002'
import logging
@ -820,4 +821,4 @@ def keyjar_init(instance, key_conf, kid_template="a%d"):
instance.keyjar.add_kb("", kb)
return jwks
return jwks

View File

@ -1,8 +1,10 @@
import copy
import uuid
import time
from oic.oic import AuthorizationRequest
__author__ = 'rohe0002'
import hmac
@ -199,7 +201,7 @@ class SessionDB(object):
sid = self.token.get_key(key)
except Exception:
raise KeyError
if sid not in self._db:
raise KeyError
else:
@ -216,7 +218,6 @@ class SessionDB(object):
Construct a sub (subject identifier)
:param sid: Session identifier
:param uid: The local user identifier
:param sector_id: Possible sector identifier
:param preferred_id_type: 'public'/'pairwise'
:return:
@ -370,10 +371,10 @@ class SessionDB(object):
access_token = self.token("T", prev=rtoken)
dic["token_expires_at"] = utc_time_sans_frac() + self.token_expires_in
#dic["client_id_issued_at"] = utc_time_sans_frac()
# dic["client_id_issued_at"] = utc_time_sans_frac()
dic["access_token"] = access_token
self._db[sid] = dic
#self._db[dic["xxxx"]] = dic
# self._db[dic["xxxx"]] = dic
return dic
else:
raise WrongTokenType("Not a refresh token!")
@ -412,7 +413,7 @@ class SessionDB(object):
return True
def is_revoked(self, sid):
#typ, sid = self.token.type_and_key(token)
# typ, sid = self.token.type_and_key(token)
try:
return self[sid]["revoked"]
except KeyError:

View File

@ -1,10 +1,12 @@
import time
from oic.oic.message import SINGLE_REQUIRED_INT
from oic.oauth2 import Message
from oic.oauth2 import SINGLE_REQUIRED_STRING
from oic.oauth2 import SINGLE_OPTIONAL_STRING
from oic.utils.time_util import epoch_in_a_while
__author__ = 'roland'
@ -14,8 +16,8 @@ class Content(Message):
"sub": SINGLE_REQUIRED_STRING, # Which subject that authenticated
"auz": SINGLE_OPTIONAL_STRING, # Authorization information
"aud": SINGLE_OPTIONAL_STRING, # The intended receiver
"val": SINGLE_REQUIRED_INT, # Valid until
"ref": SINGLE_OPTIONAL_STRING # Refresh token
"val": SINGLE_REQUIRED_INT, # Valid until
"ref": SINGLE_OPTIONAL_STRING # Refresh token
}
c_allowed_values = {"type": ["code", "access", "refresh"]}
@ -51,7 +53,7 @@ class StateLess(object):
_cont = Content(typ="code", sub=sub, aud=areq["redirect_uri"],
val=epoch_in_a_while(self.validity["grant"]))
#return _cont.to_jwe(self.keys, self.enc, self.alg)
# return _cont.to_jwe(self.keys, self.enc, self.alg)
return _cont
def upgrade_to_token(self, cont, issue_refresh=False):

View File

@ -7,7 +7,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@ -34,7 +34,7 @@ TIME_FORMAT_WITH_FRAGMENT = re.compile(
# ---------------------------------------------------------------------------
# I'm sure this is implemented somewhere else can't find it now though, so I
# made an attempt.
#Implemented according to
# Implemented according to
#http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/
#adding-durations-to-dateTimes
@ -119,7 +119,6 @@ def parse_duration(duration):
def add_duration(tid, duration):
(sign, dur) = parse_duration(duration)
if sign == '+':
@ -166,6 +165,7 @@ def add_duration(tid, duration):
else:
pass
# ---------------------------------------------------------------------------
@ -214,6 +214,7 @@ def a_while_ago(days=0, seconds=0, microseconds=0, milliseconds=0,
return time_a_while_ago(days, seconds, microseconds, milliseconds,
minutes, hours, weeks).strftime(time_format)
# ---------------------------------------------------------------------------
@ -226,6 +227,7 @@ def shift_time(dtime, shift):
"""
return dtime + timedelta(seconds=shift)
# ---------------------------------------------------------------------------
@ -254,12 +256,14 @@ def str_to_time(timestr, time_format=TIME_FORMAT):
def instant(time_format=TIME_FORMAT):
return time.strftime(time_format, time.gmtime())
# ---------------------------------------------------------------------------
def utc_now():
return calendar.timegm(time.gmtime())
# ---------------------------------------------------------------------------
@ -316,6 +320,7 @@ def utc_time_sans_frac():
def time_sans_frac():
return int("%d" % time.time())
def epoch_in_a_while(days=0, seconds=0, microseconds=0, milliseconds=0,
minutes=0, hours=0, weeks=0):
"""

View File

@ -1,19 +1,19 @@
import importlib
from tempfile import NamedTemporaryFile
from oic.utils.userinfo import UserInfo
from saml2 import saml, samlp
from saml2.client import Saml2Client
from saml2 import config
from oic.utils.userinfo import UserInfo
__author__ = 'danielevertsson'
class AaUserInfo(UserInfo):
class AaUserInfo(UserInfo):
def __init__(self, spconf, url, db=None):
UserInfo.__init__(self, db)
#Configurations for the SP handler. (pyOpSamlProxy.client.sp.conf)
# Configurations for the SP handler. (pyOpSamlProxy.client.sp.conf)
self.sp_conf = importlib.import_module(spconf)
ntf = NamedTemporaryFile(suffix="pyoidc.py", delete=True)
ntf.write("CONFIG = " + str(self.sp_conf.CONFIG).replace("%s", url))
@ -27,7 +27,7 @@ class AaUserInfo(UserInfo):
entity_id = self.sp_conf.AA_ENTITY_ID
if entity_id is None:
entity_id = self.samlcache["AA_ENTITYID"]
response = self.sp.do_attribute_query(entity_id ,
response = self.sp.do_attribute_query(entity_id,
ava[self.sp_conf.AA_NAMEID_ATTRIBUTE][0],
nameid_format=self.sp_conf.AA_NAMEID_FORMAT,
attribute=self.sp_conf.AA_REQUEST_ATTRIBUTES)

View File

@ -1,16 +1,17 @@
import copy
import logging
from oic.oic import OpenIDSchema
from oic.oic.claims_provider import ClaimsClient
from oic.utils.userinfo import UserInfo
__author__ = 'rolandh'
logger = logging.getLogger(__name__)
class DistributedAggregatedUserInfo(UserInfo):
def __init__(self, db, oidcsrv, client_info=None):
UserInfo.__init__(self, db)
self.oidcsrv = oidcsrv
@ -130,7 +131,7 @@ class DistributedAggregatedUserInfo(UserInfo):
else:
# default is what "openid" demands which is sub
#result = identity
# result = identity
result = {"sub": userid}
return OpenIDSchema(**result)

View File

@ -1,32 +1,31 @@
import logging
import ldap
from ldap import SCOPE_SUBTREE
from oic.utils.userinfo import UserInfo
__author__ = 'rolandh'
logger = logging.getLogger(__name__)
OPENID2LDAP = {
"sub": "uid",
"name": "displayName",
"given_name": "givenname",
"family_name": "sn",
"middle_name": "",
"nickname": "eduPersonNickname",
"nickname": "eduPersonNickname",
"preferred_username": "uid",
"profile": "labeledURI",
"picture": "jpegPhoto",
"website": "labeledURI",
"email": "mail",
#"email_verified":
# "email_verified":
"gender": "schacGender",
"birthdate": "schacDateOfBirth",
#zoneinfo
# zoneinfo
"locale": "preferredLanguage",
"phone_number": "telephoneNumber",
"phone_number": "telephoneNumber",
#phone_number_verified
"address": "postalAddress",
"updated_at": "" # Nothing equivalent
@ -36,9 +35,9 @@ LDAP2USERINFO = dict([(v, k) for k, v in OPENID2LDAP.items()])
class UserInfoLDAP(UserInfo):
def __init__(self, uri, base, filter_pattern, scope=SCOPE_SUBTREE,
def __init__(self, uri, base, filter_pattern, scope=ldap.SCOPE_SUBTREE,
tls=False, user="", passwd="", attr=None, attrsonly=False):
UserInfo.__init__(self, None)
super(UserInfoLDAP, self).__init__(self, None)
self.ldapuri = uri
self.base = base
self.filter_pattern = filter_pattern
@ -104,4 +103,4 @@ class UserInfoLDAP(UserInfo):
newres[key] = val
return newres
else:
return {}
return {}

View File

@ -5,8 +5,10 @@ import re
from urllib import urlencode
import urlparse
import requests
from oic.utils.time_util import in_a_while
__author__ = 'rolandh'
logger = logging.getLogger(__name__)

View File

@ -16,6 +16,7 @@ from oic.oauth2 import AccessTokenRequest
from oic.utils.authn.user import UsernamePasswordMako
from oic.utils.keyio import KeyBundle
from oic.utils.keyio import rsa_load
from utils_for_tests import URLObject, _eq
__author__ = 'rolandh'
@ -49,10 +50,6 @@ class SRV(object):
pass
def _eq(l1, l2):
return set(l1) == set(l2)
def test_1():
authn = UsernamePasswordMako(None, "login.mako", tl, PASSWD,
"authorization_endpoint")
@ -79,7 +76,9 @@ def test_3():
authn = UsernamePasswordMako(srv, "login.mako", tl, PASSWD,
"authorization_endpoint")
response, success = authn.verify(parse_qs(form))
assert response.message == "authorization_endpoint?query=foo&upm_answer=true"
url_in_response_msg = URLObject.create(response.message)
expected_url_obj = URLObject.create("authorization_endpoint?query=foo&upm_answer=true")
assert url_in_response_msg == expected_url_obj
print len(response.headers) == 2
flag = 0
for param, val in response.headers:

View File

@ -12,7 +12,6 @@ from oic.utils.keyio import RSAKey
from jwkest.jws import JWS, NoSuitableSigningKeys, WrongTypeOfKey
BASE_PATH = os.path.dirname(__file__)
RSAKEY = "%s/cert.key" % BASE_PATH
@ -29,10 +28,6 @@ JWK1 = {"keys": [
]}
def _eq(l1, l2):
return set(l1) == set(l2)
def test_chain_1():
kc = KeyBundle([{"kty": "oct", "key": "supersecret", "use": "sig"}])
assert len(kc.get("oct")) == 1

View File

@ -7,8 +7,6 @@ import base64
import random
import hmac
import hashlib
import json
import urllib
from oic.oauth2 import Grant
from oic.utils import time_util
@ -25,10 +23,7 @@ from oic.utils.authn.client import BearerHeader
from oic.utils.keyio import KeyBundle
from pytest import raises
def _eq(l1, l2):
return set(l1) == set(l2)
from utils_for_tests import URLObject, _eq
# ----------------- GRANT --------------------
@ -343,7 +338,10 @@ class TestOAuthClient():
# default == "POST"
assert uri == 'https://example.com/authz'
print body
assert body == "state=hmm&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1"
body_elts = body.split('&')
expected_body = "state=hmm&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1"
expected_body_elts = expected_body.split('&')
assert set(body_elts) == set(expected_body_elts)
assert h_args == {'headers': {'Content-type':
'application/x-www-form-urlencoded'}}
assert cis.type() == "AuthorizationRequest"
@ -352,8 +350,9 @@ class TestOAuthClient():
self.client.authorization_endpoint = "https://example.com/authz"
uri, body, h_args, cis = self.client.request_info(AuthorizationRequest,
method="GET")
assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1'
uri_obj = URLObject.create(uri)
expected_uri_obj = URLObject.create('https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1')
assert uri_obj == expected_uri_obj
assert body is None
assert h_args == {}
assert cis.type() == "AuthorizationRequest"
@ -363,8 +362,9 @@ class TestOAuthClient():
uri, body, h_args, cis = self.client.request_info(
AuthorizationRequest, method="GET", request_args={"state": "init"})
print uri
assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1'
uri_obj = URLObject.create(uri)
expected_uri_obj = URLObject.create('https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1')
assert uri_obj == expected_uri_obj
assert body is None
assert h_args == {}
assert cis.type() == "AuthorizationRequest"
@ -374,8 +374,10 @@ class TestOAuthClient():
uri, body, h_args, cis = self.client.request_info(
AuthorizationRequest, method="GET", extra_args={"rock": "little"})
print uri
assert uri == 'https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little'
uri_obj = URLObject.create(uri)
expected_uri_obj = URLObject.create('https://example.com/authz?redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little')
assert uri_obj == expected_uri_obj
assert body is None
assert h_args == {}
assert cis.type() == "AuthorizationRequest"
@ -388,8 +390,9 @@ class TestOAuthClient():
request_args={"state": "init"},
extra_args={"rock": "little"})
print uri
assert uri == 'https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little'
uri_obj = URLObject.create(uri)
expected_uri_obj = URLObject.create('https://example.com/authz?state=init&redirect_uri=http%3A%2F%2Fclient.example.com%2Fauthz&response_type=code&client_id=1&rock=little')
assert uri_obj == expected_uri_obj
assert body is None
assert h_args == {}
assert cis.type() == "AuthorizationRequest"

View File

@ -18,6 +18,8 @@ from oic.oauth2.message import TokenErrorResponse
from oic.oauth2.consumer import AuthzError
from utils_for_tests import URLObject
#from oic.oauth2.message import
# client_id=None, ca_certs=None,grant_expire_in=600, client_timeout=0,
@ -132,7 +134,9 @@ def test_consumer_begin():
url = "http://localhost:8088/authorization?%s" % urllib.urlencode(params)
assert loc == url
loc_obj = URLObject.create(loc)
url_obj = URLObject.create(url)
assert loc_obj == url_obj
def test_consumer_handle_authorization_response():
@ -265,11 +269,14 @@ def test_consumer_client_get_access_token_reques():
"urlencoded")
url, body, http_args = cons.get_access_token_request(_state)
assert url == "http://localhost:8088/token"
print body
assert body == ("code=auth_grant&client_secret=secret0&"
"grant_type=authorization_code&client_id=number5&"
"redirect_uri=https%3A%2F%2Fwww.example.com%2Foic%2Fcb")
url_obj = URLObject.create(url)
expected_url_obj = URLObject.create("http://localhost:8088/token")
assert url_obj == expected_url_obj
body_splits = body.split('&')
expected_body_splits = "code=auth_grant&client_secret=secret0&" \
"grant_type=authorization_code&client_id=number5&" \
"redirect_uri=https%3A%2F%2Fwww.example.com%2Foic%2Fcb".split('&')
assert set(body_splits) == set(expected_body_splits)
assert http_args == {'headers': {
'Content-type': 'application/x-www-form-urlencoded'}}

View File

@ -1,10 +1,14 @@
__author__ = 'rohe0002'
import json
from oic.oauth2.message import *
from jwkest.jwk import SYMKey
from pytest import raises
from utils_for_tests import URLObject, _eq
class Dummy_Message(Message):
c_param = {
@ -16,15 +20,12 @@ class Dummy_Message(Message):
"opt_json": SINGLE_OPTIONAL_JSON}
def _eq(l1, l2):
return set(l1) == set(l2)
def test_authz_req_urlencoded_1():
ar = AuthorizationRequest(response_type=["code"], client_id="foobar")
ue = ar.to_urlencoded()
print ue
assert ue == "response_type=code&client_id=foobar"
ue_splits = ue.split('&')
expected_ue_splits = "response_type=code&client_id=foobar".split('&')
assert _eq(ue_splits, expected_ue_splits)
def test_authz_req_urlencoded_2():
@ -33,8 +34,9 @@ def test_authz_req_urlencoded_2():
state="cold")
ue = ar.to_urlencoded()
print ue
assert ue == "state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar"
ue_splits = ue.split('&')
expected_ue_splits = "state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar".split('&')
assert _eq(ue_splits, expected_ue_splits)
@ -45,8 +47,9 @@ def test_authz_req_urlencoded_3():
state="xyz")
ue = ar.to_urlencoded()
print ue
assert ue == "state=xyz&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb&response_type=token&client_id=s6BhdRkqt3"
ue_splits = ue.split('&')
expected_ue_splits = "state=xyz&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb&response_type=token&client_id=s6BhdRkqt3".split('&')
assert _eq(ue_splits, expected_ue_splits)
def test_authz_req_urlencoded_4():
@ -69,8 +72,9 @@ def test_authz_req_urlencoded_5():
scope=["foo", "bar"], state="cold")
ue = ar.to_urlencoded()
print ue
assert ue == "scope=foo+bar&state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar"
ue_splits = ue.split('&')
expected_ue_splits = "scope=foo+bar&state=cold&redirect_uri=http%3A%2F%2Ffoobar.example.com%2Foaclient&response_type=code&client_id=foobar".split('&')
assert _eq(ue_splits, expected_ue_splits)
def test_authz_req_urlencoded_6():
@ -119,9 +123,12 @@ def test_authz_req_json_1():
ar = AuthorizationRequest(response_type=["code"],
client_id="foobar")
js = ar.serialize(method="json")
print js
assert js == '{"response_type": "code", "client_id": "foobar"}'
js_obj = json.loads(ar.serialize(method="json"))
expected_js_obj = {
"response_type": "code",
"client_id": "foobar"
}
assert js_obj == expected_js_obj
def test_authz_req_json_2():
@ -130,23 +137,33 @@ def test_authz_req_json_2():
redirect_uri="http://foobar.example.com/oaclient",
state="cold")
ue = ar.serialize(method="json")
print ue
assert ue == '{"state": "cold", "redirect_uri": "http://foobar.example.com/oaclient", "response_type": "code", "client_id": "foobar"}'
ue_obj = json.loads(ar.serialize(method="json"))
expected_ue_obj = {
"response_type": "code",
"state": "cold",
"redirect_uri": "http://foobar.example.com/oaclient",
"client_id": "foobar"
}
assert ue_obj == expected_ue_obj
def test_authz_req_urlencoded_3():
def test_authz_req_urlencoded_3b():
ar = AuthorizationRequest(response_type=["token"],
client_id="s6BhdRkqt3",
redirect_uri="https://client.example.com/cb",
state="xyz")
ue = ar.serialize(method="json")
print ue
assert ue == '{"state": "xyz", "redirect_uri": "https://client.example.com/cb", "response_type": "token", "client_id": "s6BhdRkqt3"}'
ue_obj = json.loads(ar.serialize(method="json"))
expected_ue_obj = {
"state": "xyz",
"redirect_uri": "https://client.example.com/cb",
"response_type": "token",
"client_id": "s6BhdRkqt3"
}
assert ue_obj == expected_ue_obj
def test_authz_req_urlencoded_4():
def test_authz_req_urlencoded_4b():
ar = AuthorizationRequest(response_type=["code"],
client_id="foobar")
@ -193,7 +210,7 @@ def test_authz_err_resp_2():
# TokenErrorResponse
def test_authz_err_resp_1():
def test_authz_err_resp_1b():
ter = TokenErrorResponse(error="access_denied", state="xyz")
assert ter
@ -202,7 +219,7 @@ def test_authz_err_resp_1():
assert _eq(ter.keys(), ['state', 'error'])
def test_authz_err_resp_2():
def test_authz_err_resp_2b():
ter = TokenErrorResponse(error="access_denied",
error_description="brewers has a four game series",
foo="bar")
@ -225,8 +242,13 @@ def test_accesstokenreponse_1():
assert at
atj = at.serialize(method="json")
print atj
assert atj == '{"token_type": "Bearer", "access_token": "SlAV32hkKG", "expires_in": 3600}'
atj_obj = json.loads(atj)
expected_atj_obj = {
"token_type": "Bearer",
"access_token": "SlAV32hkKG",
"expires_in": 3600
}
assert atj_obj == expected_atj_obj
# AccessTokenRequest
@ -238,9 +260,10 @@ def test_extra():
assert atr
query = atr.to_urlencoded()
print query
assert query == "code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F" \
"%2Fclient.example.com%2Fcb&grant_type=authorization_code&extra=foo"
query_splits = query.split('&')
expected_query_splits = "code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F" \
"%2Fclient.example.com%2Fcb&grant_type=authorization_code&extra=foo".split('&')
assert _eq(query_splits, expected_query_splits)
atr2 = AccessTokenRequest().deserialize(query, "urlencoded")
@ -338,8 +361,8 @@ def test_sp_sep_list_deserializer():
def test_json_serializer():
val = json_serializer({"foo": ["bar", "stool"]})
print val
assert val == '{"foo": ["bar", "stool"]}'
val_obj = json.loads(val)
assert val_obj == {"foo": ["bar", "stool"]}
def test_json_deserializer():
@ -528,16 +551,18 @@ def test_message():
def test_request():
req = Dummy_Message(req_str="Fair",
req_str_list=["game"]).request("http://example.com")
assert req == "http://example.com?req_str=Fair&req_str_list=game"
req_url_obj = URLObject.create(req)
expected_req_url_obj = URLObject.create("http://example.com?req_str=Fair&req_str_list=game")
assert req_url_obj == expected_req_url_obj
def test_multiple_response_types_urlencoded():
ar = AuthorizationRequest(response_type=["code", "token"],
client_id="foobar")
ue = ar.to_urlencoded()
print ue
assert ue == "response_type=code+token&client_id=foobar"
ue_splits = ue.split('&')
expected_ue_splits = "response_type=code+token&client_id=foobar".split('&')
assert _eq(ue_splits, expected_ue_splits)
are = AuthorizationRequest().deserialize(ue, "urlencoded")
assert _eq(are.keys(), ["response_type", "client_id"])
@ -548,8 +573,9 @@ def test_multiple_scopes_urlencoded():
ar = AuthorizationRequest(response_type=["code", "token"],
client_id="foobar", scope=["openid", "foxtrot"])
ue = ar.to_urlencoded()
print ue
assert ue == "scope=openid+foxtrot&response_type=code+token&client_id=foobar"
ue_splits = ue.split('&')
expected_ue_splits = "scope=openid+foxtrot&response_type=code+token&client_id=foobar".split('&')
assert _eq(ue_splits, expected_ue_splits)
are = AuthorizationRequest().deserialize(ue, "urlencoded")
assert _eq(are.keys(), ["response_type", "client_id", "scope"])
@ -561,8 +587,12 @@ def test_multiple_response_types_json():
ar = AuthorizationRequest(response_type=["code", "token"],
client_id="foobar")
ue = ar.to_json()
print ue
assert ue == '{"response_type": "code token", "client_id": "foobar"}'
ue_obj = json.loads(ue)
expected_ue_obj = {
"response_type": "code token",
"client_id": "foobar"
}
assert ue_obj == expected_ue_obj
are = AuthorizationRequest().deserialize(ue, "json")
print are.keys()
@ -574,8 +604,13 @@ def test_multiple_scopes_json():
ar = AuthorizationRequest(response_type=["code", "token"],
client_id="foobar", scope=["openid", "foxtrot"])
ue = ar.to_json()
print ue
assert ue == '{"scope": "openid foxtrot", "response_type": "code token", "client_id": "foobar"}'
ue_obj = json.loads(ue)
expected_ue_obj = {
"scope": "openid foxtrot",
"response_type": "code token",
"client_id": "foobar"
}
assert ue_obj == expected_ue_obj
are = AuthorizationRequest().deserialize(ue, "json")
assert _eq(are.keys(), ["response_type", "client_id", "scope"])

View File

@ -15,6 +15,8 @@ from oic.utils import sdb
from oic.oauth2.consumer import Consumer
from oic.oauth2.provider import Provider
from utils_for_tests import _eq
CLIENT_CONFIG = {
"client_id": "client1",
"ca_certs": "/usr/local/etc/oic/ca_certs.txt",
@ -84,10 +86,6 @@ def content_type(headers):
return "json"
def _eq(l1, l2):
return set(l1) == set(l2)
def test_provider_init():
provider = Provider("pyoicserv", sdb.SessionDB(SERVER_INFO["issuer"]), CDB,
AUTHN_BROKER, AUTHZ, verify_client)

View File

@ -44,11 +44,7 @@ from pytest import raises
from fakeoicsrv import MyFakeOICServer
def _eq(l1, l2):
s1 = set(l1)
s2 = set(l2)
return s1 == s2
from utils_for_tests import _eq
CLIENT_SECRET = "abcdefghijklmnop"

View File

@ -20,6 +20,8 @@ from oic.utils.sdb import SessionDB
from fakeoicsrv import MyFakeOICServer
from utils_for_tests import _eq
CLIENT_SECRET = "abcdefghijklmnop"
CLIENT_ID = "client_1"
@ -91,10 +93,6 @@ def start_response(status=200, headers=None):
return "status=%s, headers=%s" % (status, headers)
def _eq(l1, l2):
return set(l1) == set(l2)
def test_clean_response():
atr = AccessTokenResponse(access_token="access_token",
token_type="bearer", expires_in=600,

View File

@ -12,9 +12,7 @@ from oic.oic.message import AddressClaim
from oic.oic.message import address_deser
from oic.oic.message import Claims
def _eq(l1, l2):
return set(l1) == set(l2)
from utils_for_tests import _eq
def test_ProviderConfigurationResponse():
@ -300,11 +298,13 @@ def test_registration_request():
application_type="web",
redirect_uris=["https://example.com/authz_cb"])
js = req.to_json()
print js
assert js == '{"redirect_uris": ["https://example.com/authz_cb"], "application_type": "web", "default_acr": "foo", "require_auth_time": true, "operation": "register", "default_max_age": 10}'
js_obj = json.loads(js)
expected_js_obj = {"redirect_uris": ["https://example.com/authz_cb"], "application_type": "web", "default_acr": "foo", "require_auth_time": True, "operation": "register", "default_max_age": 10}
assert js_obj == expected_js_obj
ue = req.to_urlencoded()
print ue
assert ue == 'redirect_uris=https%3A%2F%2Fexample.com%2Fauthz_cb&application_type=web&default_acr=foo&require_auth_time=True&operation=register&default_max_age=10'
ue_splits = ue.split('&')
expected_ue_splits = 'redirect_uris=https%3A%2F%2Fexample.com%2Fauthz_cb&application_type=web&default_acr=foo&require_auth_time=True&operation=register&default_max_age=10'.split('&')
assert _eq(ue_splits, expected_ue_splits)
if __name__ == "__main__":

View File

@ -11,6 +11,8 @@ from oic.utils.sdb import ExpiredToken
from oic.oic.message import AuthorizationRequest
from oic.oic.message import OpenIDRequest
from utils_for_tests import _eq
#from oic.oauth2 import message
AREQ = AuthorizationRequest(response_type="code", client_id="client1",
@ -34,10 +36,6 @@ OAUTH2_AREQ = AuthorizationRequest(response_type="code",
BASE_URL = "https://exampl.com/"
def _eq(l1, l2):
return set(l1) == set(l2)
def test_token():
sdb = SessionDB(BASE_URL)
sid = sdb.token.key(areq=AREQ)

View File

@ -1,12 +1,10 @@
from oic.utils.stateless import StateLess
from utils_for_tests import _eq
__author__ = 'roland'
def _eq(l1, l2):
return set(l1) == set(l2)
def test_access_code():
keys = {"OCT": ["symmetric key123"]}
st = StateLess(keys, enc_alg="A128KW", enc_method="A128CBC-HS256")

View File

@ -0,0 +1,13 @@
from utils_for_tests import URLObject
__author__ = "@maennelpaennel"
def test_utils_urlobject_init():
url_1 = URLObject(host='host', resource='resource', arguments=set(['arguments']))
url_2 = URLObject(host='host', resource='resource', arguments=set(['arguments']))
assert url_1 == url_2
def test_utils_urlobject_set_by_string():
url_1 = URLObject.create('this_is_a_host/this_is_a_resource?followed_by=args&and_more=args')
url_2 = URLObject(host='this_is_a_host', resource='this_is_a_resource', arguments=set(['followed_by=args', 'and_more=args']))
assert url_1 == url_2

View File

@ -22,6 +22,7 @@ from oic.oic.claims_provider import UserClaimsResponse
from oic.oic.claims_provider import UserClaimsRequest
from oic.oic.claims_provider import ClaimsServer
from utils_for_tests import _eq
#noinspection PyUnusedLocal
def user_info(oicsrv, userdb, sub, client_id="", user_info_claims=None):
@ -92,10 +93,6 @@ USER2MODE = {"diana": "aggregate",
# ============================================================================
def _eq(l1, l2):
return set(l1) == set(l2)
def test_1():
cc = ClaimsClient(client_id="client_1")
cc.client_secret = "hemlig"

View File

@ -84,10 +84,6 @@ def content_type(headers):
return "json"
def _eq(l1, l2):
return set(l1) == set(l2)
def test_provider_init():
provider = Provider("pyoicserv", sdb.SessionDB(SERVER_INFO["issuer"]), CDB,
AUTHN_BROKER, AUTHZ,

59
tests/utils_for_tests.py Normal file
View File

@ -0,0 +1,59 @@
__author__ = "@maennelpaennel"
def _eq(l1, l2):
return set(l1) == set(l2)
class URLObject(object):
host = ''
resource = ''
arguments = set()
@classmethod
def create(klass, address):
url_obj = klass()
url_obj.set_by_string(address)
return url_obj
def __init__(self, host='', resource='', arguments=None):
self.host = host
self.resource = resource
self.arguments = arguments or set()
def __eq__(self, other):
return self.host == other.host and self.resource == other.resource \
and self.arguments == other.arguments
def set_by_string(self, address):
"""
address has the following format
"<protocol>://<host>/<resource>?<argname>=<argval>&..."
"""
address_splits = address.split('?', 1)
if len(address_splits) == 1:
host_resource = address_splits[0]
arguments_str = ''
else:
host_resource = address_splits[0]
arguments_str = address_splits[1]
self.arguments = set(arguments_str.split('&'))
host_res_splits = host_resource.split('://', 1)
if len(host_res_splits) == 1:
host_resource = host_res_splits[0]
prefix = None
else:
host_resource = host_res_splits[0]
prefix = host_res_splits[1]
host_res_splits = host_resource.split('/', 1)
if len(host_res_splits) == 1:
host = None
resource = host_res_splits[0]
else:
host = host_res_splits[0]
resource = host_res_splits[1]
if host:
self.host = host
if prefix:
self.host = "%s://%s" % (prefix, host)
self.resource = resource

23
tox.ini Normal file
View File

@ -0,0 +1,23 @@
# Tox (http://tox.testrun.org/) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.
[tox]
envlist = py27
#, py34
[testenv]
commands = python setup.py test
deps =
pytest
requests
pycrypto
mako
pyjwkest
beaker
alabaster
importlib
argparse
pyOpenSSL
cherrypy==3.2.4