├── src
└── oic
│ ├── py.typed
│ ├── extension
│ ├── __init__.py
│ ├── single.py
│ ├── heart.py
│ └── sts.py
│ ├── utils
│ ├── authn
│ │ ├── __init__.py
│ │ ├── ldap_member.py
│ │ ├── client_saml.py
│ │ └── javascript_login.py
│ ├── claims.py
│ ├── __init__.py
│ ├── userinfo
│ │ ├── __init__.py
│ │ └── aa_info.py
│ ├── shelve_wrapper.py
│ ├── template_render.py
│ ├── restrict.py
│ ├── sanitize.py
│ └── authz.py
│ ├── oauth2
│ └── exception.py
│ ├── __init__.py
│ └── exception.py
├── tests
├── __init__.py
├── utils
│ └── __init__.py
├── jwks
│ ├── jwks_fault.json
│ ├── jwks0.json
│ ├── jwks1.json
│ ├── jwks_uk.json
│ └── jwks_spo.json
├── data
│ ├── keys
│ │ ├── jwk_enc.json
│ │ ├── rsa.pub
│ │ ├── jwk.json
│ │ ├── rsa.key
│ │ ├── cert.pem
│ │ └── cert.key
│ └── templates
│ │ ├── root.mako
│ │ └── login.mako
├── rsa_enc.pub
├── rsa_enc
├── not_yet_test_x_device_flow.py
├── test_stateless.py
├── test_authn_user.py
├── conftest.py
├── test_claims.py
├── test_client_management.py
├── test_jwt.py
├── test_shelve_wrapper.py
└── test_aes.py
├── MANIFEST.in
├── oauth_example
├── rp
│ ├── __init__.py
│ ├── static
│ │ ├── robots.txt
│ │ └── style.css
│ ├── htdocs
│ │ ├── logout_done.mako
│ │ └── as_choice.mako
│ ├── templates
│ │ └── root.mako
│ └── conf.py
└── as
│ ├── static
│ └── robots.txt
│ ├── __init__.py
│ ├── tre.py
│ ├── templates
│ └── root.mako
│ ├── certs
│ ├── server.csr
│ ├── server.crt
│ └── server.key
│ ├── htdocs
│ └── login.mako
│ ├── authn_setup.py
│ ├── keys
│ └── key.pem
│ └── tre.jwks
├── oidc_example
├── rp2
│ ├── start.sh
│ ├── static
│ │ ├── robots.txt
│ │ ├── style.css
│ │ └── bootstrap
│ │ │ └── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ └── glyphicons-halflings-regular.woff
│ ├── conf.py.example
│ └── htdocs
│ │ ├── post_logout.mako
│ │ ├── opbyuid.mako
│ │ └── acrvalue.mako
├── simple_op
│ ├── src
│ │ ├── provider
│ │ │ ├── server
│ │ │ │ └── __init__.py
│ │ │ ├── __init__.py
│ │ │ └── authn
│ │ │ │ ├── util.py
│ │ │ │ ├── templates
│ │ │ │ ├── yubico_otp.jinja2
│ │ │ │ ├── mail_two_factor.jinja2
│ │ │ │ └── user_pass.jinja2
│ │ │ │ ├── __init__.py
│ │ │ │ ├── user_pass.py
│ │ │ │ └── yubikey.py
│ │ └── run.py
│ ├── yubikeys.json
│ ├── passwd.json
│ ├── requirements.txt
│ ├── users.json
│ ├── settings.yaml.example
│ └── certs
│ │ └── localhost.crt
├── op2
│ ├── requirements.txt
│ ├── start.sh
│ ├── .gitignore
│ ├── capabilities_session_mgmt.json
│ ├── static
│ │ └── bootstrap
│ │ │ └── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ └── glyphicons-halflings-regular.woff
│ ├── constraints.txt
│ ├── htdocs
│ │ ├── unauthorized.mako
│ │ ├── form_response.mako
│ │ ├── javascript_login.mako
│ │ ├── login_se.mako
│ │ ├── login.mako
│ │ └── op_session_iframe.html
│ ├── certs
│ │ ├── server.crt
│ │ └── server.key
│ ├── sp_cert
│ │ ├── localhost.crt
│ │ └── localhost.key
│ ├── client_mgr.py
│ ├── templates
│ │ ├── base.mako
│ │ └── root.mako
│ ├── cp_keys
│ │ ├── cert.pem
│ │ └── key.pem
│ ├── README.md
│ └── config_simple.py
├── rp3
│ ├── run.sh
│ ├── static
│ │ ├── robots.txt
│ │ ├── style.css
│ │ └── bootstrap
│ │ │ └── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ └── glyphicons-halflings-regular.woff
│ ├── run_heart.sh
│ ├── certs
│ │ ├── server.crt
│ │ └── server.key
│ ├── htdocs
│ │ ├── rp_session_iframe.mako
│ │ ├── opresult_repost.mako
│ │ ├── operror.mako
│ │ └── opchoice.mako
│ ├── conf_heart.py
│ ├── conf_heart.py.ex
│ ├── README
│ └── conf.py.example
├── op1
│ ├── claims_client.json
│ ├── start.sh
│ ├── cp_config.json
│ ├── create_jwk_from_cert.py
│ └── certs
│ │ ├── server.crt
│ │ └── server.key
├── simple_rp
│ ├── requirements.txt
│ ├── src
│ │ └── htdocs
│ │ │ ├── success_page.html
│ │ │ ├── index.html
│ │ │ └── repost_fragment.html
│ ├── settings.yaml.example
│ └── certs
│ │ └── localhost.crt
├── op3
│ ├── start.sh
│ ├── static
│ │ ├── bootstrap
│ │ │ └── fonts
│ │ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ │ └── glyphicons-halflings-regular.woff
│ │ └── jwks.json
│ ├── README.md
│ ├── cryptography_keys
│ │ ├── key.pem.pub
│ │ └── key.pem
│ ├── htdocs
│ │ ├── unauthorized.mako
│ │ ├── form_response.mako
│ │ ├── javascript_login.mako
│ │ ├── cp_keys
│ │ │ ├── cert.pem
│ │ │ └── key.pem
│ │ ├── login_se.mako
│ │ ├── login.mako
│ │ └── op_session_iframe.html
│ ├── certification
│ │ ├── server.crt
│ │ └── server.key
│ └── Templates
│ │ ├── base.mako
│ │ └── root.mako
└── README.md
├── docker
├── op_test
│ ├── assigned_ports.json
│ ├── https%3A%2F%2Fop%3A4433
│ │ └── default
│ ├── config.py
│ ├── run.sh
│ ├── tt_config.py
│ ├── my_jwks_60003.json
│ ├── Dockerfile
│ └── cert.pem
├── oidc_op
│ └── scripts
│ │ └── make_test_site.py
├── rp_test
│ ├── run.sh
│ ├── Dockerfile
│ └── cert.pem
├── op
│ ├── apache-ssl.conf
│ ├── run.sh
│ ├── Dockerfile
│ └── cert.pem
├── docker-compose.yml
└── integration_tests
│ ├── run.sh
│ ├── Makefile
│ └── Dockerfile
├── doc
├── _static
│ └── ViewmeonGitHub.png
├── contrib
│ ├── settings.rst
│ ├── documentation.rst
│ ├── install.rst
│ └── testing.rst
├── examples
│ ├── docker.rst
│ └── tls.rst
├── index.rst
└── conf.py
├── .readthedocs.yaml
├── .coveragerc
├── .isort.cfg
├── .github
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── python-test.yml
│ └── codeql-analysis.yml
├── setup.cfg
├── script
└── webfinger.py
├── appveyor.yml
├── pylama.ini
├── LICENSE.txt
├── mypy.ini
├── tox.ini
├── runOpRp.sh
├── .gitignore
└── Makefile
/src/oic/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include src/oic/py.typed
2 |
--------------------------------------------------------------------------------
/oauth_example/rp/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "roland"
2 |
--------------------------------------------------------------------------------
/oidc_example/rp2/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./rp2.py &
3 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/server/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/oic/extension/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "roland"
2 |
--------------------------------------------------------------------------------
/src/oic/utils/authn/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = "rolandh"
2 |
--------------------------------------------------------------------------------
/oauth_example/as/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
--------------------------------------------------------------------------------
/oauth_example/rp/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
--------------------------------------------------------------------------------
/oidc_example/op2/requirements.txt:
--------------------------------------------------------------------------------
1 | CherryPy<=8.9.1
2 | oic
3 |
--------------------------------------------------------------------------------
/oidc_example/rp2/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 |
--------------------------------------------------------------------------------
/oidc_example/rp3/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./rp3.py -p 8088 -k conf &
--------------------------------------------------------------------------------
/oidc_example/rp3/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/yubikeys.json:
--------------------------------------------------------------------------------
1 | {
2 | "abcdefghijkl": "diana"
3 | }
--------------------------------------------------------------------------------
/docker/op_test/assigned_ports.json:
--------------------------------------------------------------------------------
1 | {"https://op:4433][default": 60003}
2 |
--------------------------------------------------------------------------------
/oidc_example/op1/claims_client.json:
--------------------------------------------------------------------------------
1 | {"client_1":{"client_secret": "hemlig"}}
--------------------------------------------------------------------------------
/oidc_example/rp3/run_heart.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ./rp3.py -p 8088 -k conf_heart &
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'regu0004'
2 |
--------------------------------------------------------------------------------
/oidc_example/simple_rp/requirements.txt:
--------------------------------------------------------------------------------
1 | cherrypy==3.2.4
2 | pyaml==15.03.1
3 |
--------------------------------------------------------------------------------
/oauth_example/as/__init__.py:
--------------------------------------------------------------------------------
1 | # A basic example of a OAuth2 Authorization Server
2 |
--------------------------------------------------------------------------------
/oidc_example/op1/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | ./oc_server.py -p 8092 -d oc_config &
3 |
--------------------------------------------------------------------------------
/oidc_example/op2/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | ./server.py -p 8040 -t -d config_simple.py
3 |
--------------------------------------------------------------------------------
/oauth_example/rp/static/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | min-height: 2000px;
3 | padding-top: 70px;
4 | }
--------------------------------------------------------------------------------
/oidc_example/rp2/static/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | min-height: 2000px;
3 | padding-top: 70px;
4 | }
--------------------------------------------------------------------------------
/oidc_example/rp3/static/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | min-height: 2000px;
3 | padding-top: 70px;
4 | }
--------------------------------------------------------------------------------
/doc/_static/ViewmeonGitHub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/doc/_static/ViewmeonGitHub.png
--------------------------------------------------------------------------------
/oidc_example/simple_op/passwd.json:
--------------------------------------------------------------------------------
1 | {
2 | "diana": "krall",
3 | "babs": "howes",
4 | "upper": "crust"
5 | }
--------------------------------------------------------------------------------
/oauth_example/rp/htdocs/logout_done.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 | <%def name="title()">Log out done%def>
3 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/requirements.txt:
--------------------------------------------------------------------------------
1 | cherrypy==3.2.4
2 | pyaml==15.03.1
3 | Jinja2==2.11.3
4 | yubico-client==1.9.1
5 |
--------------------------------------------------------------------------------
/oidc_example/op3/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | ./server.py -c config -d &
3 |
4 | # -c: configuration file
5 | # -d: debug
6 |
7 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/run.py:
--------------------------------------------------------------------------------
1 | from provider.server.server import main
2 |
3 | if __name__ == "__main__":
4 | main()
5 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | python:
4 | install:
5 | - path: .
6 | extra_requirements:
7 | - docs
8 |
--------------------------------------------------------------------------------
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | branch = True
3 |
4 | [report]
5 | exclude_lines =
6 | pragma: no cover
7 | raise NotImplementedError
8 |
--------------------------------------------------------------------------------
/doc/contrib/settings.rst:
--------------------------------------------------------------------------------
1 | Settings
2 | ========
3 |
4 | .. automodule:: oic.utils.settings
5 | :members:
6 | :show-inheritance:
7 |
--------------------------------------------------------------------------------
/.isort.cfg:
--------------------------------------------------------------------------------
1 | [settings]
2 | force_single_line = 1
3 | known_first_party = oic
4 | known_third_party = jwkest,pytest
5 | default_section = THIRDPARTY
6 |
--------------------------------------------------------------------------------
/oidc_example/op2/.gitignore:
--------------------------------------------------------------------------------
1 | venv
2 | client_db*
3 | config.py
4 | sp_cert/*
5 | !sp_cert/localhost.crt
6 | !sp_cert/localhost.key
7 | static/jwks.json
8 |
--------------------------------------------------------------------------------
/oidc_example/op2/capabilities_session_mgmt.json:
--------------------------------------------------------------------------------
1 | {
2 | "check_session_iframe": "https://localhost:8080/check_session",
3 | "subject_types_supported": ["public", "pairwise"]
4 | }
--------------------------------------------------------------------------------
/oidc_example/op2/static/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/op2/static/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/oidc_example/op2/static/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/op2/static/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/oidc_example/op3/static/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/op3/static/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/oidc_example/op3/static/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/op3/static/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/oidc_example/rp2/static/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/rp2/static/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/oidc_example/rp2/static/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/rp2/static/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/oidc_example/rp3/static/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/rp3/static/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/oidc_example/rp3/static/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/rp3/static/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/oidc_example/op2/static/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/op2/static/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/oidc_example/op3/static/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/op3/static/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/oidc_example/rp2/static/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/rp2/static/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/oidc_example/rp3/static/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infohash/pyoidc/master/oidc_example/rp3/static/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/tests/jwks/jwks_fault.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "n": 1194457323795445980561452000539327328778638467,
5 | "e": 65537,
6 | "kty": "RSA",
7 | "kid": "rsa1"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | - [ ] Any changes relevant to users are recorded in the `CHANGELOG.md`.
2 | - [ ] The documentation has been updated, if necessary.
3 | - [ ] New code is annotated.
4 | - [ ] Changes are covered by tests.
5 | ---
6 |
--------------------------------------------------------------------------------
/oidc_example/op3/README.md:
--------------------------------------------------------------------------------
1 | # OIDCProvider
2 | An example of OpenID Connect Provider based on pyoidc.
3 |
4 | This example is a simplified version of pyoidc "op2" example available at:
5 | https://github.com/CZ-NIC/pyoidc/tree/master/oidc_example/op2
6 |
--------------------------------------------------------------------------------
/tests/data/keys/jwk_enc.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "kty": "oct",
5 | "k": "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow",
6 | "kid": "HMAC key used in JWS spec Appendix A.1 example"}
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [pydocstyle]
2 | convention = google
3 | add-ignore =
4 | D1, # Ignore missing docstrings
5 | D212, # Multiline docstring not on first line
6 | D413, # No blank line after last section
7 | add-select =
8 | D213 # Multiline docstring should start on first line
9 |
--------------------------------------------------------------------------------
/tests/rsa_enc.pub:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIc+q8Y+q4qjw/SMMRzwyfJ7Iv
3 | IQ7Q3WSE+x2Z61bwh4luI65HzARW3X9NkD8kHAh/Vxaz/wS86FXALTGygoKQ8ETO
4 | C7WNz/4g/z9VHowcZPO/jwdTzfo+2nK3Xg9qSAWF6x5jnSaFsuvcotcrxpke9gVC
5 | q+MkEDDzeKOAiHJnNwIDAQAB
6 | -----END PUBLIC KEY-----
--------------------------------------------------------------------------------
/script/webfinger.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from oic.oauth2 import PBase
4 | from oic.utils.webfinger import OIC_ISSUER
5 | from oic.utils.webfinger import WebFinger
6 |
7 | __author__ = 'roland'
8 |
9 | wf = WebFinger(OIC_ISSUER)
10 | wf.httpd = PBase()
11 | print (wf.discovery_query(sys.argv[1]))
12 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | image:
2 | - Visual Studio 2019
3 |
4 | environment:
5 | matrix:
6 | - TOXENV: py37
7 | - TOXENV: py38
8 | - TOXENV: py39
9 | - TOXENV: py310
10 |
11 | build: off
12 |
13 | install:
14 | - py -m pip install --upgrade pip tox
15 |
16 | test_script:
17 | - py -m tox
18 |
--------------------------------------------------------------------------------
/oidc_example/op1/cp_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseurl":"https://localhost:8093",
3 | "issuer": "https://www.kodtest.se/rolandsCP",
4 | "keys": {
5 | "rsa": {
6 | "key":"cp_keys/key.pem",
7 | "jwk": "cp_keys/pub.jwk",
8 | "cert": "cp_keys/cert.pem"
9 | }}
10 | }
--------------------------------------------------------------------------------
/tests/data/keys/rsa.pub:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD6vqn19W/VB215DBADRakfPmCt
3 | FBf8/+YyhGqixWIwDiEl/L6Lw5HKZCUPVgrC0ADhJfvAbn4fte5MWBCTkqgepKL3
4 | BySMA0LMaBF12pbHlPSUbmQGBJmTX4NNXuUel6TbPYJAU2Nh5Nan0Mb7Bmb8QpFv
5 | S0Hw7qZRW8y2eIttfwIDAQAB
6 | -----END PUBLIC KEY-----
7 |
--------------------------------------------------------------------------------
/docker/op_test/https%3A%2F%2Fop%3A4433/default:
--------------------------------------------------------------------------------
1 | {"tool": {"issuer": "https://op:4433", "tag": "default", "webfinger_email": "acct:foobar@op:4433", "webfinger_url": "https://op:4433/foobar", "acr_values": ["session urn:mace:incommon:iap:bronze"], "insecure": true, "login_hint": "bob@example.com", "profile": "CT.T.T.T.ens.+"}}
--------------------------------------------------------------------------------
/pylama.ini:
--------------------------------------------------------------------------------
1 | [pylama]
2 | linters = pyflakes,eradicate,pycodestyle,mccabe
3 | # D203/D204 and D212/D213 are mutually exclusive, pick one
4 | # E203 is not PEP8 compliant in pycodestyle
5 | ignore = D203,D212,E203,C901
6 |
7 | [pylama:pycodestyle]
8 | max_line_length = 120
9 |
10 | [pylama:mccabe]
11 | complexity = 30
12 |
--------------------------------------------------------------------------------
/src/oic/extension/single.py:
--------------------------------------------------------------------------------
1 | class SingleService(object):
2 | def __init__(self, host):
3 | self.host = host
4 | self.endpoints = {} # type: ignore
5 |
6 |
7 | class SingleClient(object):
8 | def __init__(self, host):
9 | self.host = host
10 | self.requests = {} # type: ignore
11 |
--------------------------------------------------------------------------------
/tests/jwks/jwks0.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "kty": "RSA",
5 | "e": "AQAB",
6 | "kid": "abc",
7 | "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/oauth_example/as/tre.py:
--------------------------------------------------------------------------------
1 | from oic.utils.keyio import build_keyjar
2 | from oic.utils.keyio import dump_jwks
3 |
4 | __author__ = "roland"
5 |
6 | key_conf = [{"type": "RSA", "use": ["enc", "sig"]}]
7 |
8 | pub_jwks, keyjar, kdd = build_keyjar(key_conf, "tre%d", None, None)
9 |
10 | dump_jwks(keyjar.issuer_keys[""], "tre.jwks")
11 |
--------------------------------------------------------------------------------
/oidc_example/simple_rp/src/htdocs/success_page.html:
--------------------------------------------------------------------------------
1 |
2 |
RP Auth Success
3 |
4 |
5 | Authorization code:
6 |
7 | {0}
8 |
9 |
10 |
11 | Access token:
12 |
13 | {1}
14 |
15 |
16 | Id token:
17 |
18 | {2}
19 |
20 |
21 | User info:
22 |
23 | {3}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/authn/util.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | class JSONDictDB(object):
5 | def __init__(self, json_path):
6 | with open(json_path, "r") as f:
7 | self._db = json.load(f)
8 |
9 | def __getitem__(self, item):
10 | return self._db[item]
11 |
12 | def __contains__(self, item):
13 | return item in self._db
14 |
--------------------------------------------------------------------------------
/docker/oidc_op/scripts/make_test_site.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 |
4 | from oidctest.site_setup import oidc_op_setup
5 |
6 | _distroot = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../.."))
7 |
8 | _root = 'test_site'
9 |
10 | if os.path.isdir(_root) is False:
11 | os.makedirs(_root)
12 |
13 | os.chdir(_root)
14 |
15 | oidc_op_setup(_distroot)
16 |
--------------------------------------------------------------------------------
/oidc_example/op2/constraints.txt:
--------------------------------------------------------------------------------
1 | alabaster==0.7.12
2 | asn1crypto==0.24.0
3 | Beaker==1.10.1
4 | certifi==2018.11.29
5 | cffi==1.12.1
6 | chardet==3.0.4
7 | CherryPy==8.9.1
8 | cryptography==2.5
9 | future==0.17.1
10 | idna==2.8
11 | Mako==1.0.7
12 | MarkupSafe==1.1.1
13 | oic==0.15.1
14 | pycparser==2.19
15 | pycryptodomex==3.7.3
16 | pyjwkest==1.4.0
17 | requests==2.21.0
18 | six==1.12.0
19 | urllib3==1.24.1
20 |
--------------------------------------------------------------------------------
/oidc_example/simple_rp/src/htdocs/index.html:
--------------------------------------------------------------------------------
1 |
2 | Test RP
3 |
4 | Example OpenID Connect RP
5 |
6 | Enter UID to select OpenID Connect provider:
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/oidc_example/op3/cryptography_keys/key.pem.pub:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6LC5Zr1Ng3HN/RF173gS
3 | AtcWo3RbnRc+YtE2BZnmNDVe2cepFmMjYbcum6bonS7JWCTDYd5m0Gt7+yh71YQx
4 | F3bjXAEXGbR6w1405emJuurFgfAnwk8h+o//+DYoF4E9WdbHfi9wRa7tS8pAB2o1
5 | JpsH1r3O7wCSPb/cDRIQZ3R5ORjl+q/PWUFxAjLKe2IAM2rfJulertITnGlxcnzz
6 | y9cnIyYgY+gm17hZFZd1qLpNG10McyzlwxPl6c+7PagS2nx9Mdv4gUvaNwzgkzQQ
7 | h9viJfBggc1o86CEPg8RAOqWjUJ8jHAYJDeRxEFHKGcbOXa2n1ZOBj+FHprIOg60
8 | XwIDAQAB
9 | -----END RSA PUBLIC KEY-----
--------------------------------------------------------------------------------
/doc/contrib/documentation.rst:
--------------------------------------------------------------------------------
1 | .. _documentation:
2 |
3 | Documentation
4 | #############
5 |
6 | PyOIDC uses Sphinx_ for documentation.
7 |
8 | You can install it via Pip_:
9 |
10 | .. _Pip: https://pip.pypa.io/en/stable/installing/
11 | .. _Sphinx: https://www.sphinx-doc.org/
12 |
13 | ::
14 |
15 | $ pip install .[docs]
16 |
17 | To build the documentation, run:
18 |
19 | ::
20 |
21 | $ make help
22 |
23 | To have the changes automatically shown while you're hacking, run:
24 |
25 | ::
26 |
27 | $ make livehtml
28 |
--------------------------------------------------------------------------------
/docker/rp_test/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | trap 'kill ${!}; term_handler' SIGHUP SIGINT SIGQUIT SIGTERM
4 |
5 | term_handler() {
6 | echo "term_handler"
7 | killall python3
8 | exit 143; # 128 + 15 -- SIGTERM
9 | }
10 |
11 | echo -n "Starting config_server.py ... "
12 | python3 server.py -f flows -p 8080 -k -t conf &
13 | if [ $? -eq 0 ] ; then
14 | echo "OK"
15 | else
16 | echo "ERROR"
17 | exit -1
18 | fi
19 |
20 | while true
21 | do
22 | tail -f /dev/null & wait ${!}
23 | done
24 |
25 | echo "exited $0"
26 |
--------------------------------------------------------------------------------
/docker/op_test/config.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | BASEDIR = os.path.abspath(os.path.dirname(__file__))
4 |
5 | SERVER_CERT = "certs/cert.pem"
6 | SERVER_KEY = "certs/key.pem"
7 | CA_BUNDLE = None
8 |
9 | VERIFY_SSL = False
10 |
11 | PORT_MIN = 60001
12 | PORT_MAX = 61000
13 |
14 | BASE_URL = 'https://op-test'
15 |
16 | # The variables below are all passed on to the test tool instance
17 | ENT_PATH = 'entities'
18 | ENT_INFO = 'entity_info'
19 |
20 | FLOWDIR = 'flows'
21 |
22 | PATH2PORT = 'path2port.csv'
23 | TEST_SCRIPT = './op_test_tool.py'
24 |
--------------------------------------------------------------------------------
/tests/data/keys/jwk.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "alg": "RS256",
5 | "e": "AQAB",
6 | "kid": "abc",
7 | "kty": "RSA",
8 | "use": "sig",
9 | "n": "pKybs0WaHU_y4cHxWbm8Wzj66HtcyFn7Fh3n-99qTXu5yNa30MRYIYfSDwe9JVc1JUoGw41yq2StdGBJ40HxichjE-Yopfu3B58QlgJvToUbWD4gmTDGgMGxQxtv1En2yedaynQ73sDpIK-12JJDY55pvf-PCiSQ9OjxZLiVGKlClDus44_uv2370b9IN2JiEOF-a7JBqaTEYLPpXaoKWDSnJNonr79tL0T7iuJmO1l705oO3Y0TQ-INLY6jnKG_RpsvyvGNnwP9pMvcP1phKsWZ10ofuuhJGRp8IxQL9RfzT87OvF0RBSO1U73h09YP-corWDsnKIi6TbzRpN5YDw"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/docker/op_test/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | trap 'kill ${!}; term_handler' SIGHUP SIGINT SIGQUIT SIGTERM
4 |
5 | term_handler() {
6 | echo "term_handler"
7 | killall python3
8 | exit 143; # 128 + 15 -- SIGTERM
9 | }
10 |
11 | echo -n "Starting config_server.py ... "
12 | python3 config_server.py -t -k -p 60000 -H html -c tt_config config &
13 | if [ $? -eq 0 ] ; then
14 | echo "OK"
15 | else
16 | echo "ERROR"
17 | exit -1
18 | fi
19 |
20 | while true
21 | do
22 | tail -f /dev/null & wait ${!}
23 | done
24 |
25 | echo "exited $0"
26 |
--------------------------------------------------------------------------------
/docker/op/apache-ssl.conf:
--------------------------------------------------------------------------------
1 |
2 | Listen 4433
3 |
4 | DocumentRoot /var/www/html
5 |
6 | #LogLevel info ssl:warn
7 | ErrorLog ${APACHE_LOG_DIR}/error.log
8 | CustomLog ${APACHE_LOG_DIR}/access.log combined
9 |
10 | SSLEngine on
11 | SSLCertificateFile /etc/apache2/cert.pem
12 | SSLCertificateKeyFile /etc/apache2/key.pem
13 |
14 | RequestHeader set X-Forwarded-Proto "https"
15 | ProxyPass / http://127.0.0.1:3000/
16 | ProxyPassReverse / http://127.0.0.1:3000/
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/oic/utils/claims.py:
--------------------------------------------------------------------------------
1 | __author__ = "rolandh"
2 |
3 |
4 | class ClaimsMode(object):
5 | def __init__(self, user2mode):
6 | self.user2mode = user2mode
7 |
8 | def aggregate(self, uid, info=None):
9 | """
10 | Determine whether the claims for a user should be aggregated.
11 |
12 | :param uid: user id
13 | :param info: claims
14 | :return: True if the claims should be aggregated, otherwist False
15 | """
16 | if uid in self.user2mode and self.user2mode[uid] == "aggregate":
17 | return True
18 |
19 | return False
20 |
--------------------------------------------------------------------------------
/oidc_example/rp2/conf.py.example:
--------------------------------------------------------------------------------
1 | PORT = 8666
2 | #BASE = "http://lingon.catalogix.se:" + str(PORT) + "/"
3 | #BASE = "http://hashog.umdc.umu.se:" + str(PORT) + "/"
4 | BASE = "http://localhost:" + str(PORT) + "/"
5 |
6 | # If BASE is https these has to be specified
7 | SERVER_KEY = ''
8 | SERVER_CERT = ''
9 | CA_BUNDLE = None
10 |
11 | # information used when registering the client
12 | ME = {
13 | "application_type": "web",
14 | "application_name": "idpproxy",
15 | "contacts": ["ops@example.com"],
16 | }
17 |
18 | # Which scopes to use
19 | SCOPE = ["openid", "profile", "email", "address", "phone"]
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/authn/templates/yubico_otp.jinja2:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Please login
7 |
8 |
9 |
10 | Yubikey OTP (One Time Password)
11 |
12 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (C) 2017 Roland Hedberg, Sweden
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/oidc_example/op1/create_jwk_from_cert.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from oic.oauth2 import PBase
4 | from oic.utils.keystore import KeyStore
5 | from oic.utils.keystore import x509_rsa_loads
6 |
7 | __author__ = 'rohe0002'
8 |
9 | def main(x509_file, out="keys.jwk"):
10 | pb = PBase()
11 | ks = KeyStore(pb.http_request)
12 |
13 | key = x509_rsa_loads(open(x509_file).read())
14 | ks.add_key(key, "rsa", "sig")
15 |
16 | f = open(out, "w")
17 | txt = ks.dumps("sig")
18 | f.write(txt)
19 | f.close()
20 |
21 | if __name__ == "__main__":
22 | import sys
23 | main(*sys.argv[1:2])
24 |
--------------------------------------------------------------------------------
/tests/jwks/jwks1.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "n": "zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFYInq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVbCGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znanLwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MXsGxBHf3AKT5w",
5 | "e": "AQAB",
6 | "kty": "RSA",
7 | "kid": "rsa1"
8 | },
9 | {
10 | "k": "YTEyZjBlMDgxMGI4YWU4Y2JjZDFiYTFlZTBjYzljNDU3YWM0ZWNiNzhmNmFlYTNkNTY0NzMzYjE",
11 | "kty": "oct"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/tests/jwks/jwks_uk.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "n": "zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFYInq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVbCGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znanLwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MXsGxBHf3AKT5w",
5 | "e": "AQAB",
6 | "kty": "RSA",
7 | "kid": "rsa1"
8 | },
9 | {
10 | "k": "YTEyZjBlMDgxMGI4YWU4Y2JjZDFiYTFlZTBjYzljNDU3YWM0ZWNiNzhmNmFlYTNkNTY0NzMzYjE",
11 | "kty": "buz"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/oidc_example/op2/htdocs/unauthorized.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%inherit file="base.mako"/>
4 |
5 | <%block name="title">
6 | Unauthorized
7 | ${parent.title()}
8 | %block>
9 |
10 | <%block name="headline">
11 |
12 |
17 | %block>
18 |
19 | <%block name="body">
20 |
23 | %block>
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/unauthorized.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%inherit file="base.mako"/>
4 |
5 | <%block name="title">
6 | Unauthorized
7 | ${parent.title()}
8 | %block>
9 |
10 | <%block name="headline">
11 |
12 |
17 | %block>
18 |
19 | <%block name="body">
20 |
23 | %block>
--------------------------------------------------------------------------------
/oidc_example/op2/htdocs/form_response.mako:
--------------------------------------------------------------------------------
1 | <%!
2 | def inputs(form_args):
3 | """
4 | Creates list of input elements
5 | """
6 | element = ""
7 | for name, value in form_args.items():
8 | element += "" % (name,
9 | value)
10 | return element
11 | %>
12 |
13 |
14 |
15 | Submit This Form
16 |
17 |
18 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/form_response.mako:
--------------------------------------------------------------------------------
1 | <%!
2 | def inputs(form_args):
3 | """
4 | Creates list of input elements
5 | """
6 | element = ""
7 | for name, value in form_args.items():
8 | element += "" % (name,
9 | value)
10 | return element
11 | %>
12 |
13 |
14 |
15 | Submit This Form
16 |
17 |
18 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/docker/op/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | trap 'kill ${!}; term_handler' SIGHUP SIGINT SIGQUIT SIGTERM
4 |
5 | pid=0
6 |
7 | term_handler() {
8 | echo "term_handler"
9 | service ntp stop
10 | if [ $pid -ne 0 ]; then
11 | kill -SIGTERM "$pid"
12 | wait "$pid"
13 | fi
14 | exit 143; # 128 + 15 -- SIGTERM
15 | }
16 |
17 | service ntp start
18 | service apache2 start
19 |
20 | echo -n "Starting node example ... "
21 | node certification/oidc &
22 | pid="$!"
23 | if [ $? -eq 0 ] ; then
24 | echo "OK"
25 | else
26 | echo "ERROR"
27 | exit -1
28 | fi
29 |
30 | while true
31 | do
32 | tail -f /dev/null & wait ${!}
33 | done
34 |
35 | echo "exited $0"
36 |
--------------------------------------------------------------------------------
/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | op-test:
4 | build:
5 | context: ..
6 | dockerfile: docker/op_test/Dockerfile
7 | ports:
8 | - "60000-60010:60000-60010"
9 | rp-test:
10 | build:
11 | context: ..
12 | dockerfile: docker/rp_test/Dockerfile
13 | ports:
14 | - "8080:8080"
15 | op:
16 | build:
17 | context: ..
18 | dockerfile: docker/op/Dockerfile
19 | ports:
20 | - "4433:4433"
21 | environment:
22 | - ISSUER=https://op:4433
23 | - NODE_ENV=production
24 | - DEBUG=oidc-provider:*
25 | - NODE_TLS_REJECT_UNAUTHORIZED=0
26 | links:
27 | - op-test
28 |
--------------------------------------------------------------------------------
/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | check_untyped_defs = True
3 | no_implicit_optional = True
4 |
5 | [mypy-jwkest.*]
6 | ignore_missing_imports = True
7 |
8 | [mypy-saml2.*]
9 | ignore_missing_imports = True
10 |
11 | [mypy-ldap.*]
12 | ignore_missing_imports = True
13 |
14 | [mypy-cryptography.*]
15 | ignore_missing_imports = True
16 |
17 | [mypy-defusedxml.*]
18 | ignore_missing_imports = True
19 |
20 | [mypy-pytest.*]
21 | ignore_missing_imports = True
22 |
23 | [mypy-responses.*]
24 | ignore_missing_imports = True
25 |
26 | [mypy-freezegun.*]
27 | ignore_missing_imports = True
28 |
29 | [mypy-testfixtures.*]
30 | ignore_missing_imports = True
31 |
32 | [mypy-mako.*]
33 | ignore_missing_imports = True
34 |
--------------------------------------------------------------------------------
/oauth_example/as/templates/root.mako:
--------------------------------------------------------------------------------
1 | <%def name="pre()" filter="trim">
2 |
5 | %def>
6 | <%def name="post()" filter="trim">
7 |
8 |
11 |
12 | %def>
13 | ##
15 |
16 | OAuth test
17 | ${self.css()}
18 |
19 |
20 |
21 | ${pre()}
22 | ${next.body()}
23 | ${post()}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/oauth_example/as/certs/server.csr:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE REQUEST-----
2 | MIIBqDCCARECAQAwUTELMAkGA1UEBhMCU0UxEzARBgNVBAgTClNvbWUtU3RhdGUx
3 | DDAKBgNVBAoTA1VtVTEMMAoGA1UECxMDSVRTMREwDwYDVQQDEwhyb2hlMDAwMjCB
4 | nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5zbNbHIYIkGGJ3RGdRKkYmF4gOor
5 | v5eDuUKTVtuu3VvxrpOWvwnFV+NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnk
6 | FqzPRx6bHgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR+gxDbh/D5TXuUqScO
7 | OqR47vSpIbUH+ncCAwEAAaAXMBUGCSqGSIb3DQEJBzEIEwZmb29iYXIwDQYJKoZI
8 | hvcNAQEFBQADgYEAY3aUO7bJxGOmqUtBTTFeDkuJutUk2KQjvycVOkCy9QdbYPyL
9 | vtwJGfNN1cLpdSdiEICtwGg1XfjCZQBRPrXOSBiCfmPkchVlw9QXzluPeIJ7oFnZ
10 | fi9I6u+7D3ZmRVSwZmrRIcj9fb/v6ohAKPVr8520HkGD3mKUkXMyTcXLFjo=
11 | -----END CERTIFICATE REQUEST-----
12 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/authn/templates/mail_two_factor.jinja2:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Please login
7 |
8 |
9 |
10 | Second part of authentication
11 |
12 | Check your registered mail {{ mail }}, then enter the received code
13 | below:
14 |
15 |
25 |
26 |
--------------------------------------------------------------------------------
/oauth_example/rp/templates/root.mako:
--------------------------------------------------------------------------------
1 | <%def name="pre()" filter="trim">
2 |
5 | %def>
6 | <%def name="post()" filter="trim">
7 |
8 |
11 |
12 | %def>
13 | ##
15 |
16 | OAuth test
17 |
18 |
19 |
20 | ${pre()}
21 | ## ${comps.dict_to_table(pageargs)}
22 | ##
23 | ${next.body()}
24 | ${post()}
25 |
26 |
27 |
--------------------------------------------------------------------------------
/docker/op_test/tt_config.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | BASEDIR = os.path.abspath(os.path.dirname(__file__))
4 |
5 | SERVER_CERT = "certs/cert.pem"
6 | SERVER_KEY = "certs/key.pem"
7 | CA_BUNDLE = None
8 |
9 | VERIFY_SSL = False
10 |
11 | # Make sure BASE starts with https if TLS = True
12 | BASE = 'https://op-test'
13 |
14 | ENT_PATH = 'entities'
15 | ENT_INFO = 'entity_info'
16 | PRE_HTML = 'html/tt'
17 |
18 | KEYS = [
19 | {"key": "keys/enc.key", "type": "RSA", "use": ["enc"]},
20 | {"key": "keys/sig.key", "type": "RSA", "use": ["sig"]},
21 | {"crv": "P-256", "type": "EC", "use": ["sig"]},
22 | {"crv": "P-256", "type": "EC", "use": ["enc"]}
23 | ]
24 |
25 | SESSION_CHANGE_URL = "{}session_change"
26 | SESSION_UNCHANGE_URL = "{}session_unchange"
27 | SESSION_MAX_CHECKS = 3
28 |
--------------------------------------------------------------------------------
/oidc_example/simple_rp/settings.yaml.example:
--------------------------------------------------------------------------------
1 | # parameters for registration with the provider
2 | registration_info:
3 | application_type: web
4 | application_name: "Example RP"
5 | # only has support for using the first redirect_uri and response_type
6 | redirect_uris:
7 | #- "{base}/code_flow"
8 | #- "{base}/implicit_hybrid_flow"
9 | - "{base}:{port}/implicit_hybrid_flow"
10 | response_types:
11 | #- code
12 | - code id_token token
13 |
14 | # parameters for authentication request
15 | behaviour:
16 | scope:
17 | - openid
18 | - profile
19 | acr_values:
20 | - password
21 | - mail_two_factor
22 | - yubikey
23 |
24 |
25 | server:
26 | cert: certs/localhost.crt
27 | key: certs/localhost.key
28 | cert_chain:
29 | verify_ssl: False
30 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/authn/templates/user_pass.jinja2:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Please login
7 |
8 |
9 |
10 | {{ page_header }}
11 |
12 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/oauth_example/rp/conf.py:
--------------------------------------------------------------------------------
1 | from mako.lookup import TemplateLookup
2 |
3 | PORT = 8666
4 | HOST = "localhost"
5 |
6 | BASE = "http://%s:%d/" % (HOST, PORT)
7 |
8 | # If BASE is https these has to be specified
9 | SERVER_KEY = ""
10 | SERVER_CERT = ""
11 | CA_BUNDLE = None
12 |
13 | SCOPE = []
14 |
15 | ROOT = "./"
16 | LOOKUP = TemplateLookup(
17 | directories=[ROOT + "templates", ROOT + "htdocs"],
18 | module_directory=ROOT + "modules",
19 | input_encoding="utf-8",
20 | output_encoding="utf-8",
21 | )
22 |
23 | AS_CONF = {
24 | "AuthzServer@DIG": {
25 | "authorization_endpoint": "https://localhost:8080/authorization",
26 | "token_endpoint": "https://localhost:8080/token",
27 | "client_id": "YWwQiwQNWaeI",
28 | "client_secret": "cdb8c2f40110a5fdefe7e26ea26a0bd51fb3d1b9593d6a054c75abcb",
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/oauth_example/as/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICGTCCAYICCQCIs8fF+AnxUzANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJT
3 | RTETMBEGA1UECBMKU29tZS1TdGF0ZTEMMAoGA1UEChMDVW1VMQwwCgYDVQQLEwNJ
4 | VFMxETAPBgNVBAMTCHJvaGUwMDAyMB4XDTExMDkwNzA4MjMwOFoXDTEyMDkwNjA4
5 | MjMwOFowUTELMAkGA1UEBhMCU0UxEzARBgNVBAgTClNvbWUtU3RhdGUxDDAKBgNV
6 | BAoTA1VtVTEMMAoGA1UECxMDSVRTMREwDwYDVQQDEwhyb2hlMDAwMjCBnzANBgkq
7 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKT
8 | Vtuu3VvxrpOWvwnFV+NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6b
9 | HgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR+gxDbh/D5TXuUqScOOqR47vSp
10 | IbUH+ncCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDP9PE53utRqocZpFRxrhL+4vcI
11 | vlQd3XonE7vMJwdl9FUW7QRMon19dpYKQ6LTCOBA4ZCwh2z/Om2X97zogMLKFPcE
12 | LVqxzBVlrzuqAgOErEalYv9pCBzoFHGUHP6kTAUOCsoO9ZdQWgA6YkK2hYRSlLNX
13 | Z0wHIHGaHe5xnFFpyQ==
14 | -----END CERTIFICATE-----
15 |
--------------------------------------------------------------------------------
/oidc_example/op1/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICGTCCAYICCQCIs8fF+AnxUzANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJT
3 | RTETMBEGA1UECBMKU29tZS1TdGF0ZTEMMAoGA1UEChMDVW1VMQwwCgYDVQQLEwNJ
4 | VFMxETAPBgNVBAMTCHJvaGUwMDAyMB4XDTExMDkwNzA4MjMwOFoXDTEyMDkwNjA4
5 | MjMwOFowUTELMAkGA1UEBhMCU0UxEzARBgNVBAgTClNvbWUtU3RhdGUxDDAKBgNV
6 | BAoTA1VtVTEMMAoGA1UECxMDSVRTMREwDwYDVQQDEwhyb2hlMDAwMjCBnzANBgkq
7 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKT
8 | Vtuu3VvxrpOWvwnFV+NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6b
9 | HgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR+gxDbh/D5TXuUqScOOqR47vSp
10 | IbUH+ncCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDP9PE53utRqocZpFRxrhL+4vcI
11 | vlQd3XonE7vMJwdl9FUW7QRMon19dpYKQ6LTCOBA4ZCwh2z/Om2X97zogMLKFPcE
12 | LVqxzBVlrzuqAgOErEalYv9pCBzoFHGUHP6kTAUOCsoO9ZdQWgA6YkK2hYRSlLNX
13 | Z0wHIHGaHe5xnFFpyQ==
14 | -----END CERTIFICATE-----
15 |
--------------------------------------------------------------------------------
/oidc_example/op2/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICGTCCAYICCQCIs8fF+AnxUzANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJT
3 | RTETMBEGA1UECBMKU29tZS1TdGF0ZTEMMAoGA1UEChMDVW1VMQwwCgYDVQQLEwNJ
4 | VFMxETAPBgNVBAMTCHJvaGUwMDAyMB4XDTExMDkwNzA4MjMwOFoXDTEyMDkwNjA4
5 | MjMwOFowUTELMAkGA1UEBhMCU0UxEzARBgNVBAgTClNvbWUtU3RhdGUxDDAKBgNV
6 | BAoTA1VtVTEMMAoGA1UECxMDSVRTMREwDwYDVQQDEwhyb2hlMDAwMjCBnzANBgkq
7 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKT
8 | Vtuu3VvxrpOWvwnFV+NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6b
9 | HgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR+gxDbh/D5TXuUqScOOqR47vSp
10 | IbUH+ncCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDP9PE53utRqocZpFRxrhL+4vcI
11 | vlQd3XonE7vMJwdl9FUW7QRMon19dpYKQ6LTCOBA4ZCwh2z/Om2X97zogMLKFPcE
12 | LVqxzBVlrzuqAgOErEalYv9pCBzoFHGUHP6kTAUOCsoO9ZdQWgA6YkK2hYRSlLNX
13 | Z0wHIHGaHe5xnFFpyQ==
14 | -----END CERTIFICATE-----
15 |
--------------------------------------------------------------------------------
/oidc_example/rp3/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICGTCCAYICCQCIs8fF+AnxUzANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJT
3 | RTETMBEGA1UECBMKU29tZS1TdGF0ZTEMMAoGA1UEChMDVW1VMQwwCgYDVQQLEwNJ
4 | VFMxETAPBgNVBAMTCHJvaGUwMDAyMB4XDTExMDkwNzA4MjMwOFoXDTEyMDkwNjA4
5 | MjMwOFowUTELMAkGA1UEBhMCU0UxEzARBgNVBAgTClNvbWUtU3RhdGUxDDAKBgNV
6 | BAoTA1VtVTEMMAoGA1UECxMDSVRTMREwDwYDVQQDEwhyb2hlMDAwMjCBnzANBgkq
7 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKT
8 | Vtuu3VvxrpOWvwnFV+NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6b
9 | HgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR+gxDbh/D5TXuUqScOOqR47vSp
10 | IbUH+ncCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDP9PE53utRqocZpFRxrhL+4vcI
11 | vlQd3XonE7vMJwdl9FUW7QRMon19dpYKQ6LTCOBA4ZCwh2z/Om2X97zogMLKFPcE
12 | LVqxzBVlrzuqAgOErEalYv9pCBzoFHGUHP6kTAUOCsoO9ZdQWgA6YkK2hYRSlLNX
13 | Z0wHIHGaHe5xnFFpyQ==
14 | -----END CERTIFICATE-----
15 |
--------------------------------------------------------------------------------
/.github/workflows/python-test.yml:
--------------------------------------------------------------------------------
1 | name: Run tests and quality control
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 | schedule:
9 | - cron: '15 6 * * *'
10 |
11 | jobs:
12 | build:
13 |
14 | runs-on: ubuntu-latest
15 | strategy:
16 | max-parallel: 4
17 | matrix:
18 | python: [3.7, 3.8, 3.9, "3.10", "3.11"]
19 |
20 | steps:
21 | - uses: actions/checkout@v3
22 | - name: Set up Python
23 | uses: actions/setup-python@v4
24 | with:
25 | python-version: ${{ matrix.python }}
26 | - name: Install dependencies
27 | run: |
28 | python -m pip install --upgrade pip
29 | pip install tox
30 | - name: Run tests
31 | run: |
32 | tox
33 | - name: Upload Coverage to Codecov
34 | uses: codecov/codecov-action@v3
35 |
--------------------------------------------------------------------------------
/oidc_example/op3/certification/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICGTCCAYICCQCIs8fF+AnxUzANBgkqhkiG9w0BAQUFADBRMQswCQYDVQQGEwJT
3 | RTETMBEGA1UECBMKU29tZS1TdGF0ZTEMMAoGA1UEChMDVW1VMQwwCgYDVQQLEwNJ
4 | VFMxETAPBgNVBAMTCHJvaGUwMDAyMB4XDTExMDkwNzA4MjMwOFoXDTEyMDkwNjA4
5 | MjMwOFowUTELMAkGA1UEBhMCU0UxEzARBgNVBAgTClNvbWUtU3RhdGUxDDAKBgNV
6 | BAoTA1VtVTEMMAoGA1UECxMDSVRTMREwDwYDVQQDEwhyb2hlMDAwMjCBnzANBgkq
7 | hkiG9w0BAQEFAAOBjQAwgYkCgYEA5zbNbHIYIkGGJ3RGdRKkYmF4gOorv5eDuUKT
8 | Vtuu3VvxrpOWvwnFV+NY0LgqkQSMMyVzodJE3SUuwQTUHPXXY5784vnkFqzPRx6b
9 | HgPxKz7XfwQjEBTafQTMmOeYI8wFIOIHY5i0RWR+gxDbh/D5TXuUqScOOqR47vSp
10 | IbUH+ncCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDP9PE53utRqocZpFRxrhL+4vcI
11 | vlQd3XonE7vMJwdl9FUW7QRMon19dpYKQ6LTCOBA4ZCwh2z/Om2X97zogMLKFPcE
12 | LVqxzBVlrzuqAgOErEalYv9pCBzoFHGUHP6kTAUOCsoO9ZdQWgA6YkK2hYRSlLNX
13 | Z0wHIHGaHe5xnFFpyQ==
14 | -----END CERTIFICATE-----
15 |
--------------------------------------------------------------------------------
/doc/contrib/install.rst:
--------------------------------------------------------------------------------
1 | .. _install:
2 |
3 | Development Install
4 | ###################
5 |
6 | Firstly, fork_ the project and get a local copy with:
7 |
8 | ::
9 |
10 | $ git clone git@github.com:/pyoidc.git
11 |
12 | .. _fork: https://github.com/CZ-NIC/pyoidc/issues#fork-destination-box
13 |
14 | PyOIDC supports Python 3.
15 |
16 | Installation via a `virtual environment`_ is **highly** recommended.
17 |
18 | .. _virtual environment: http://docs.python-guide.org/en/latest/dev/virtualenvs/
19 |
20 | Install dependencies (using Pip_) via:
21 |
22 | .. _Pip: pip.pypa.io/en/stable/installing/
23 |
24 | ::
25 |
26 | $ make install
27 |
28 | .. Note:: The dependencies will require that you compile your Python source code
29 | with byte-compiling. This means avoiding the ``-B`` option and
30 | not setting ``PYTHONDONTWRITEBYTECODE``.
31 |
--------------------------------------------------------------------------------
/oidc_example/op2/sp_cert/localhost.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICIzCCAYwCAXcwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCc2UxCzAJBgNV
3 | BAgTAmFjMQ0wCwYDVQQHEwRVbWVhMQwwCgYDVQQKEwNJVFMxDTALBgNVBAsTBERJ
4 | UkcxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xNDAzMTkxNzE5MzlaFw0yNDAzMTYx
5 | NzE5MzlaMFoxCzAJBgNVBAYTAnNlMQswCQYDVQQIEwJhYzENMAsGA1UEBxMEVW1l
6 | YTEMMAoGA1UEChMDSVRTMQ0wCwYDVQQLEwRESVJHMRIwEAYDVQQDEwlsb2NhbGhv
7 | c3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALswQbMz6dKL4FEKu+O3GYDf
8 | aniyxcfizsHaiehuh5jufrlGZw/zMMttteTRhpjtTFN2/R68d1kh8pmO+HV7u+53
9 | h+C33I178ZsOquSovGe1AWmzDzp2j6CRdQYdZaMCc4YxtwEXs7570YmnPLKhz8aH
10 | diQRHhtx1cqdPPStkz67AgMBAAEwDQYJKoZIhvcNAQELBQADgYEApQ5znEdhsJBs
11 | +ew81X9pkUKZ/ruu/p2OPfYmKzdFnK6mq9bF5CEIaIkvbSJjpECicmGCNw9ATJXy
12 | lnwFLnfxw6d+YGi4XPuo64NSG00ycnMSTMJ8OR5ForcF89v72BLRDYo6yXeNDw72
13 | 2ul0lPzH54CNQzsm4N/5w5iStnOT1TQ=
14 | -----END CERTIFICATE-----
15 |
--------------------------------------------------------------------------------
/oidc_example/op2/client_mgr.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import json
3 |
4 | from oic.utils.client_management import CDB
5 |
6 | if __name__ == '__main__':
7 | import argparse
8 |
9 | parser = argparse.ArgumentParser()
10 | parser.add_argument('-l', dest='list', action='store_true')
11 | parser.add_argument('-a', dest='add')
12 | parser.add_argument('-d', dest='delete')
13 | parser.add_argument(dest="config")
14 | args = parser.parse_args()
15 |
16 | # Client data base
17 | cdb = CDB(args.config)
18 |
19 | if args.list:
20 | for key, val in cdb.items():
21 | print('{}:{}'.format(key, val['redirect_uris']))
22 |
23 | if args.add:
24 | fp = open(args.add)
25 | spec = json.load(fp)
26 | cli_info = cdb.create(**spec)
27 | print(cli_info)
28 |
29 | if args.delete:
30 | del cdb[args.delete]
31 |
--------------------------------------------------------------------------------
/src/oic/utils/authn/ldap_member.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from oic.utils.userinfo.ldap_info import UserInfoLDAP
4 |
5 | __author__ = "haho0032"
6 |
7 | logger = logging.getLogger(__name__)
8 |
9 |
10 | class UserLDAPMemberValidation(UserInfoLDAP):
11 | def __init__(self, verify_attr=None, verify_attr_valid=None, **kwargs):
12 | UserInfoLDAP.__init__(self, **kwargs)
13 | self.verify_attr = verify_attr
14 | self.verify_attr_valid = verify_attr_valid
15 |
16 | def __call__(self, userid, **kwargs):
17 | result = UserInfoLDAP.__call__(self, userid, None, False)
18 | if self.verify_attr in result:
19 | for field in result[self.verify_attr]:
20 | if field in self.verify_attr_valid:
21 | return True
22 | logger.warning(userid + "tries to use the service with the values " + result)
23 | return False
24 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | envlist = py{37,38,39,310,311},docs,quality
3 | skip_missing_interpreters = True
4 |
5 | [testenv]
6 | commands =
7 | py.test --cov-report=xml --cov=oic {posargs:tests}
8 | extras = testing
9 | deps =
10 | pytest-cov
11 |
12 | [testenv:docs]
13 | whitelist_externals = make
14 | extras = docs
15 | commands = sphinx-build -b html doc/ doc/_build/html -W
16 |
17 | [testenv:quality]
18 | ignore_errors = True
19 | deps = twine
20 | extras =
21 | quality
22 | types
23 | commands =
24 | isort --diff --check-only src/ tests/
25 | pylama src/ tests/
26 | pydocstyle src
27 | mypy --config-file mypy.ini src/ tests/
28 | black src/ tests/ --check -t py36
29 | python3 setup.py --quiet sdist
30 | bandit -a file -r src/ oauth_example/ oidc_example/
31 | twine check dist/*
32 |
33 | [pep8]
34 | max-line-length=100
35 |
36 | [pytest]
37 | addopts = --color=yes
38 |
--------------------------------------------------------------------------------
/runOpRp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Check if running on mac
4 | if [ "$(uname)" = "Darwin" ]; then
5 | # Check so the boot2docker vm is running
6 | if [ "$(boot2docker status)" != "running" ]; then
7 | boot2docker start
8 | fi
9 | boot2docker shellinit
10 | HOST_IP=$(boot2docker ip)
11 | else
12 | # if running on linux
13 | if [ "$(id -u)" -ne 0 ]; then
14 | sudo="sudo"
15 | fi
16 | HOST_IP=$(ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | grep -v '172.17' | cut -d: -f2 | awk '{ print $1}' | head -1)
17 | fi
18 |
19 | echo "HOST IP: " "${HOST_IP}"
20 |
21 | ${sudo} docker run -d \
22 | --name op \
23 | -p 8092:8092 \
24 | -e HOST_IP="${HOST_IP}" \
25 | -i -t \
26 | itsdirg/pyoidc_example_op
27 |
28 | ${sudo} docker run -d \
29 | --name rp \
30 | -p 8666:8666 \
31 | -e HOST_IP="${HOST_IP}" \
32 | -i -t \
33 | itsdirg/pyoidc_example_rp
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IntelliJ project folder
2 | .idea
3 |
4 | # Other dev-env folders and files
5 | .vagrant
6 | .vscode
7 | Vagrantfile
8 | Pipfile
9 | Pipfile.lock
10 |
11 | # setup.py-related folders and files
12 | build
13 | dist
14 | *.egg-info
15 | *.egg
16 | *.eggs
17 |
18 | # Compiled files
19 | *.pyc
20 | *.pyo
21 |
22 | # Logs
23 | *.log
24 | *.log.*
25 |
26 | # Tox testing
27 | .tox
28 | private/
29 | tmp/
30 | keys/
31 | secret/
32 | pyoidc*
33 | foo.*
34 |
35 | # Testing stuff
36 | .coverage
37 | .cache/
38 | .pytest_cache
39 | .mypy_cache
40 |
41 | # Dynamically created doc folders
42 | doc/_build
43 | !tests/data/keys
44 |
45 | # Remaining stuff
46 | oidc_example/op1/client_db.db
47 | oidc_example/op1/oc_config.py
48 | oidc_example/rp3/conf.py
49 | oidc_example/rp3/modules/
50 | oauth_example/rp/modules/
51 | oauth_example/as/modules/
52 | oauth_example/as/static/jwks.json
53 | oauth_example/as/client_db.*
54 | update
55 |
--------------------------------------------------------------------------------
/tests/rsa_enc:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQCIc+q8Y+q4qjw/SMMRzwyfJ7IvIQ7Q3WSE+x2Z61bwh4luI65H
3 | zARW3X9NkD8kHAh/Vxaz/wS86FXALTGygoKQ8ETOC7WNz/4g/z9VHowcZPO/jwdT
4 | zfo+2nK3Xg9qSAWF6x5jnSaFsuvcotcrxpke9gVCq+MkEDDzeKOAiHJnNwIDAQAB
5 | AoGANM43HyTDpycqHYt5AiFQTx87k4WFiErFJblQYUpz4K1y/86LGXnYjA03wLp7
6 | 1OuMVktLm+iq2rhGxxI2U1CyWfgWnJHfvZgojjcUHd4fRm5U16fzCKgnl3ZtC0fG
7 | mxmpbq1f+h1nhgK4cNi6s3boz+GfdrdT5MvshRRT8z/zINECQQC41xgat9yRAHO2
8 | y9+fqrnOQlSL/uObm8NqmuKPiqJRsqBqGPYuDyeJlx1I3mxkCL7Q/WqmfjFlqIeB
9 | Zp4BnmyFAkEAvPwBzUFylaKLwUVcZmGXbHzo9G4oauRe6Vj+um7eXinz1D+X5ReJ
10 | BHa6Su+4xHOE9myEMZ6P80F+BnLuepH/iwJAMRbGywm7ZTMGiCx61k+kCvgotgla
11 | b1AdxOkfdFmwJBxZZ/P7JV5W9L6SQ3D2vlZoPt6efVsUSVhJrH8RRYLKdQJBALzG
12 | HiahkYvW6jMMzdeW9GLyAuDmiIj9xbDhrNEdnhIBZgZF37x/XeaPklb4TmAt5Esi
13 | 6omGEdSzPufCNmVJITECQEDD6V9ojDly//wsTTPykgiXmLiETAH9Ff6I6Zp2g5d7
14 | VcNvzfoQ3BegXbYuJzSFanCWNk/2+9GPptlcdMbGjo4=
15 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/tests/data/keys/rsa.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQD6vqn19W/VB215DBADRakfPmCtFBf8/+YyhGqixWIwDiEl/L6L
3 | w5HKZCUPVgrC0ADhJfvAbn4fte5MWBCTkqgepKL3BySMA0LMaBF12pbHlPSUbmQG
4 | BJmTX4NNXuUel6TbPYJAU2Nh5Nan0Mb7Bmb8QpFvS0Hw7qZRW8y2eIttfwIDAQAB
5 | AoGBAJVf9FxkRKUB8cOE3h006JWGUY2KROghgn9hxy0ErYO3RyQcN1+HuFh75GAI
6 | gAyiYYO/XwS6TkSR2057wBRJ8ABzcL3+v5g+16Vbh0BjXVE+cv1WGdNGujyzl6ji
7 | jlyF4cb6tXDyqWTLkMAtV20NfO/CGsfii6YEkZb2P90usthRAkEA/oG7a9EvQ7eR
8 | gSEqppzW7KCwidPjnZTr/ROIZQU33nwkIJ0ElTjMNYKP8DerSuixR9skw2ZY8Q8I
9 | 1PTBnocHwwJBAPw3SAQYwxZwQMu1trVPMNOGIbSY4rQlMZGXrCZSu/TnozczFLA8
10 | qNM84g5veyJOzHKmYkIsMG1gwg5VNniG45UCQF6SlLOW0upl70K9sVyiUVcyywcc
11 | Xqty6FJtjLSFQOKC3OXlkwtkRLXpo1UPSq6WUzIxY7LceFZzUMPZg41F/gMCQHNr
12 | POqbBlPzZMOUUZthNP/nhu8lc8Fqr+dnmGElRVxK0JdHKfWInN2mI/DlNV064Dar
13 | S5XqsPKs78EtX7MCT40CQFQZiry8m7ROubOU4+HDG9o1w9zcKXCkmbD9hBCGvTAj
14 | BQNuGE0DtC6FEWTs8bXybLM5yBRq1XiKLdmi5N+3n4g=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oauth_example/as/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQDnNs1schgiQYYndEZ1EqRiYXiA6iu/l4O5QpNW267dW/Guk5a/
3 | CcVX41jQuCqRBIwzJXOh0kTdJS7BBNQc9ddjnvzi+eQWrM9HHpseA/ErPtd/BCMQ
4 | FNp9BMyY55gjzAUg4gdjmLRFZH6DENuH8PlNe5SpJw46pHju9KkhtQf6dwIDAQAB
5 | AoGAKuSxy1KHQ6OgPaWGhKWGtXGbp17J6usy1qWRK+XpVMt/1IEw0BQB9kII8f+Y
6 | dfq//6UNBJI7kEMbn1dD+nNpF4ncO9QWHE5oqacHgaZOl6+MF3ePy8aXkADhwiel
7 | L7CtZjhwbcjGt5PI6AIcpFfmBAbu5Pf4gidr6bR+MoJGlhECQQDzfMaRqruJkqsz
8 | Z5b9boIr08orx1xPoHTmE5g0ET9+UJy/BBgx7DNv+AQhJ2UC1ZaKcgqwetOwJhQs
9 | u8Cbrct9AkEA8xiQSwqlM7ltpNl6L2VvSxzTd897it+FJElXbD6u80RvzMuo3Xw3
10 | +M+F0kDobM4vsyBuZRw418/yOpnOv8x4AwJATj5WgRDgWwEqysYLGz2bzwGsAg16
11 | eIwThKvfSTwRr0GwXSGvtLs2fFCy4wSJzTNdwPeMv9F4nS5fZVCgQGbE8QJAMZBG
12 | iyZGfH9H/Z5hrRwvTs83xmvFMpFUIgvaCTXWkb7YVJcJfO8AsngNPssBGH4Jd6ob
13 | F/5jEI1TQ+NsJerYZQJBAJdqDlnPQyqek4kdBvwh2hYo9EwOrgOchmruMOeP5lE6
14 | 2TLIyjYC3uVMPJj+ESayVcAMrgj4Enk4qh/WKVeMJ7c=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oidc_example/op1/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQDnNs1schgiQYYndEZ1EqRiYXiA6iu/l4O5QpNW267dW/Guk5a/
3 | CcVX41jQuCqRBIwzJXOh0kTdJS7BBNQc9ddjnvzi+eQWrM9HHpseA/ErPtd/BCMQ
4 | FNp9BMyY55gjzAUg4gdjmLRFZH6DENuH8PlNe5SpJw46pHju9KkhtQf6dwIDAQAB
5 | AoGAKuSxy1KHQ6OgPaWGhKWGtXGbp17J6usy1qWRK+XpVMt/1IEw0BQB9kII8f+Y
6 | dfq//6UNBJI7kEMbn1dD+nNpF4ncO9QWHE5oqacHgaZOl6+MF3ePy8aXkADhwiel
7 | L7CtZjhwbcjGt5PI6AIcpFfmBAbu5Pf4gidr6bR+MoJGlhECQQDzfMaRqruJkqsz
8 | Z5b9boIr08orx1xPoHTmE5g0ET9+UJy/BBgx7DNv+AQhJ2UC1ZaKcgqwetOwJhQs
9 | u8Cbrct9AkEA8xiQSwqlM7ltpNl6L2VvSxzTd897it+FJElXbD6u80RvzMuo3Xw3
10 | +M+F0kDobM4vsyBuZRw418/yOpnOv8x4AwJATj5WgRDgWwEqysYLGz2bzwGsAg16
11 | eIwThKvfSTwRr0GwXSGvtLs2fFCy4wSJzTNdwPeMv9F4nS5fZVCgQGbE8QJAMZBG
12 | iyZGfH9H/Z5hrRwvTs83xmvFMpFUIgvaCTXWkb7YVJcJfO8AsngNPssBGH4Jd6ob
13 | F/5jEI1TQ+NsJerYZQJBAJdqDlnPQyqek4kdBvwh2hYo9EwOrgOchmruMOeP5lE6
14 | 2TLIyjYC3uVMPJj+ESayVcAMrgj4Enk4qh/WKVeMJ7c=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oidc_example/op2/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQDnNs1schgiQYYndEZ1EqRiYXiA6iu/l4O5QpNW267dW/Guk5a/
3 | CcVX41jQuCqRBIwzJXOh0kTdJS7BBNQc9ddjnvzi+eQWrM9HHpseA/ErPtd/BCMQ
4 | FNp9BMyY55gjzAUg4gdjmLRFZH6DENuH8PlNe5SpJw46pHju9KkhtQf6dwIDAQAB
5 | AoGAKuSxy1KHQ6OgPaWGhKWGtXGbp17J6usy1qWRK+XpVMt/1IEw0BQB9kII8f+Y
6 | dfq//6UNBJI7kEMbn1dD+nNpF4ncO9QWHE5oqacHgaZOl6+MF3ePy8aXkADhwiel
7 | L7CtZjhwbcjGt5PI6AIcpFfmBAbu5Pf4gidr6bR+MoJGlhECQQDzfMaRqruJkqsz
8 | Z5b9boIr08orx1xPoHTmE5g0ET9+UJy/BBgx7DNv+AQhJ2UC1ZaKcgqwetOwJhQs
9 | u8Cbrct9AkEA8xiQSwqlM7ltpNl6L2VvSxzTd897it+FJElXbD6u80RvzMuo3Xw3
10 | +M+F0kDobM4vsyBuZRw418/yOpnOv8x4AwJATj5WgRDgWwEqysYLGz2bzwGsAg16
11 | eIwThKvfSTwRr0GwXSGvtLs2fFCy4wSJzTNdwPeMv9F4nS5fZVCgQGbE8QJAMZBG
12 | iyZGfH9H/Z5hrRwvTs83xmvFMpFUIgvaCTXWkb7YVJcJfO8AsngNPssBGH4Jd6ob
13 | F/5jEI1TQ+NsJerYZQJBAJdqDlnPQyqek4kdBvwh2hYo9EwOrgOchmruMOeP5lE6
14 | 2TLIyjYC3uVMPJj+ESayVcAMrgj4Enk4qh/WKVeMJ7c=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oidc_example/rp3/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQDnNs1schgiQYYndEZ1EqRiYXiA6iu/l4O5QpNW267dW/Guk5a/
3 | CcVX41jQuCqRBIwzJXOh0kTdJS7BBNQc9ddjnvzi+eQWrM9HHpseA/ErPtd/BCMQ
4 | FNp9BMyY55gjzAUg4gdjmLRFZH6DENuH8PlNe5SpJw46pHju9KkhtQf6dwIDAQAB
5 | AoGAKuSxy1KHQ6OgPaWGhKWGtXGbp17J6usy1qWRK+XpVMt/1IEw0BQB9kII8f+Y
6 | dfq//6UNBJI7kEMbn1dD+nNpF4ncO9QWHE5oqacHgaZOl6+MF3ePy8aXkADhwiel
7 | L7CtZjhwbcjGt5PI6AIcpFfmBAbu5Pf4gidr6bR+MoJGlhECQQDzfMaRqruJkqsz
8 | Z5b9boIr08orx1xPoHTmE5g0ET9+UJy/BBgx7DNv+AQhJ2UC1ZaKcgqwetOwJhQs
9 | u8Cbrct9AkEA8xiQSwqlM7ltpNl6L2VvSxzTd897it+FJElXbD6u80RvzMuo3Xw3
10 | +M+F0kDobM4vsyBuZRw418/yOpnOv8x4AwJATj5WgRDgWwEqysYLGz2bzwGsAg16
11 | eIwThKvfSTwRr0GwXSGvtLs2fFCy4wSJzTNdwPeMv9F4nS5fZVCgQGbE8QJAMZBG
12 | iyZGfH9H/Z5hrRwvTs83xmvFMpFUIgvaCTXWkb7YVJcJfO8AsngNPssBGH4Jd6ob
13 | F/5jEI1TQ+NsJerYZQJBAJdqDlnPQyqek4kdBvwh2hYo9EwOrgOchmruMOeP5lE6
14 | 2TLIyjYC3uVMPJj+ESayVcAMrgj4Enk4qh/WKVeMJ7c=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oidc_example/op2/sp_cert/localhost.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQC7MEGzM+nSi+BRCrvjtxmA32p4ssXH4s7B2onoboeY7n65RmcP
3 | 8zDLbbXk0YaY7UxTdv0evHdZIfKZjvh1e7vud4fgt9yNe/GbDqrkqLxntQFpsw86
4 | do+gkXUGHWWjAnOGMbcBF7O+e9GJpzyyoc/Gh3YkER4bcdXKnTz0rZM+uwIDAQAB
5 | AoGAF8uTnn8r6xri4gp2RgVBlbNQ6pT3NWisldH9E/HxBMzUiSLc+RcWDdYdeD/2
6 | VzxbJoUKujyFA2ygVUrqZKzc/8TBc0VAljjKtcoj4w3DshjzYFXa7zJ1b3D0NYoA
7 | FARFHJL45o/SGSjBkMSqAs2jSVp2zebbQwsNHzH8Co7/lHkCQQDfXt1NNjLMG8FA
8 | qRzckIf5ZYLUkKUt+2p2+oFMjSctkwvCcU86yWIJIqpSFoiwXHWieOuNj8tbdwp+
9 | sFSBvUBdAkEA1ohVKfCUecksOTLBgkbboEbWFY1FEdzTe77QN6UDRcUSuRk2za89
10 | aqQCU0/o3usYqzbq9x8EVO2xPlC/6aRp9wJACm0QIVF9T3+gJpd+LGFmp2Jwl+Fk
11 | hF/u2TzaGiugf4UUkG/fhdvugoSmtIwutySprPq96+6hTFSjHcS3PRMLVQJAF2o/
12 | 6Vjxy60SX5fTmRWEySSSHz4RCNcSWhJEhZ5EEixlU8CVw7NZv7bw7gjtwM7mHWHc
13 | GWbQQTjEPKnxmF2ylwJBALqeTnvDZyqD3yJcRH5mRlCIZZOo90f9VumXBDyFG5ya
14 | /ozazEN8n18J/Y7RkTl59oYnJn7WeOsYvFSbm3VUiaQ=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oidc_example/op3/certification/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXAIBAAKBgQDnNs1schgiQYYndEZ1EqRiYXiA6iu/l4O5QpNW267dW/Guk5a/
3 | CcVX41jQuCqRBIwzJXOh0kTdJS7BBNQc9ddjnvzi+eQWrM9HHpseA/ErPtd/BCMQ
4 | FNp9BMyY55gjzAUg4gdjmLRFZH6DENuH8PlNe5SpJw46pHju9KkhtQf6dwIDAQAB
5 | AoGAKuSxy1KHQ6OgPaWGhKWGtXGbp17J6usy1qWRK+XpVMt/1IEw0BQB9kII8f+Y
6 | dfq//6UNBJI7kEMbn1dD+nNpF4ncO9QWHE5oqacHgaZOl6+MF3ePy8aXkADhwiel
7 | L7CtZjhwbcjGt5PI6AIcpFfmBAbu5Pf4gidr6bR+MoJGlhECQQDzfMaRqruJkqsz
8 | Z5b9boIr08orx1xPoHTmE5g0ET9+UJy/BBgx7DNv+AQhJ2UC1ZaKcgqwetOwJhQs
9 | u8Cbrct9AkEA8xiQSwqlM7ltpNl6L2VvSxzTd897it+FJElXbD6u80RvzMuo3Xw3
10 | +M+F0kDobM4vsyBuZRw418/yOpnOv8x4AwJATj5WgRDgWwEqysYLGz2bzwGsAg16
11 | eIwThKvfSTwRr0GwXSGvtLs2fFCy4wSJzTNdwPeMv9F4nS5fZVCgQGbE8QJAMZBG
12 | iyZGfH9H/Z5hrRwvTs83xmvFMpFUIgvaCTXWkb7YVJcJfO8AsngNPssBGH4Jd6ob
13 | F/5jEI1TQ+NsJerYZQJBAJdqDlnPQyqek4kdBvwh2hYo9EwOrgOchmruMOeP5lE6
14 | 2TLIyjYC3uVMPJj+ESayVcAMrgj4Enk4qh/WKVeMJ7c=
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/authn/__init__.py:
--------------------------------------------------------------------------------
1 | import importlib
2 | from oic.utils.authn.user import UserAuthnMethod
3 |
4 | __author__ = 'regu0004'
5 |
6 | class AuthnModule(UserAuthnMethod):
7 |
8 | # override in subclass specifying suitable url endpoint to POST user input
9 | url_endpoint = "/verify"
10 | FAILED_AUTHN = (None, True)
11 |
12 | def __call__(self, *args, **kwargs):
13 | """
14 | Display user interaction.
15 | :return: instance of oic.utils.http_util.Response
16 | """
17 | raise NotImplementedError()
18 |
19 | def verify(self, *args, **kwargs):
20 | """
21 | Callback to verify user input
22 | :return: username of the authenticated user
23 | """
24 | raise NotImplementedError()
25 |
26 |
27 | def make_cls_from_name(name):
28 | module_name, cls_name = name.rsplit(".", 1)
29 | cls = getattr(importlib.import_module(module_name), cls_name)
30 | return cls
31 |
--------------------------------------------------------------------------------
/doc/examples/docker.rst:
--------------------------------------------------------------------------------
1 | Run Example with Docker
2 | =======================
3 |
4 | So, you just want to see how it works?
5 |
6 | In order to get started, you'll need to install Docker_. Once installed, please
7 | run the `runOpRp.sh`_ script in the root of the repository.
8 |
9 | .. _Docker: https://docs.docker.com/get-docker/
10 | .. _runOpRp.sh: https://github.com/CZ-NIC/pyoidc/blob/master/runOpRp.sh
11 |
12 | This will set up the following:
13 |
14 | * An OP listening at port ``localhost:8088``.
15 | * An RP listening at port ``localhost:8666``.
16 |
17 | You can check this is the case by running:
18 |
19 | ::
20 |
21 | $ docker ps -a
22 |
23 | Go ahead and visit the RP at ``localhost:8666``. You can now login with the
24 | following UID:
25 |
26 | * ``username@localhost:8093``
27 |
28 | You will then be re-directed to the OP, where you will be asked to enter your
29 | username and password. Please use the following:
30 |
31 | * ``username: diana``
32 | * ``password: krall``
33 |
--------------------------------------------------------------------------------
/tests/not_yet_test_x_device_flow.py:
--------------------------------------------------------------------------------
1 | from oic.extension.device_flow import AuthorizationRequest
2 | from oic.extension.device_flow import DeviceFlowClient
3 | from oic.extension.device_flow import DeviceFlowServer
4 | from oic.extension.device_flow import TokenRequest
5 | from oic.oauth2 import Client
6 | from oic.oauth2 import Server
7 |
8 |
9 | def test_device_flow():
10 | _client = Client()
11 | cli = DeviceFlowClient(_client)
12 |
13 | _server = Server()
14 | srv = DeviceFlowServer(_server)
15 |
16 | # init
17 | req = AuthorizationRequest(
18 | client_id=cli.host.client_id, response_type="device_code"
19 | )
20 |
21 | resp = srv.device_endpoint(req)
22 |
23 | # Polling
24 |
25 | req2 = TokenRequest(
26 | grant_type="urn:ietf:params:oauth:grant-type:device_code",
27 | device_code=resp["device_dode"],
28 | client_id=cli.host.client_id,
29 | )
30 |
31 | resp = srv.token_endpoint(req2)
32 |
33 | # Authorization Pending
34 |
35 | # Do Authorization
36 |
--------------------------------------------------------------------------------
/tests/test_stateless.py:
--------------------------------------------------------------------------------
1 | from oic.utils.stateless import StateLess
2 |
3 | __author__ = "roland"
4 |
5 |
6 | def _eq(l1, l2):
7 | return set(l1) == set(l2)
8 |
9 |
10 | def test_access_code():
11 | keys = {"oct": ["symmetric key123"]} # keylength 16 bytes=128 bits
12 | st = StateLess(keys, enc_alg="A128KW", enc_method="A128CBC-HS256")
13 | con = st.create_authz_session("subject", {"redirect_uri": "https://example.com"})
14 | tok = st.get_token(con)
15 |
16 | _info = st[tok]
17 | assert _eq(_info.keys(), ["typ", "aud", "val", "sub"])
18 | assert _info["sub"] == "subject"
19 | assert _info["typ"] == "code"
20 | assert _info["aud"] == "https://example.com"
21 |
22 |
23 | def test_update_to_access_token():
24 | keys = {"oct": ["symmetric key123"]}
25 | st = StateLess(keys, enc_alg="A128KW", enc_method="A128CBC-HS256")
26 | tok = st.create_authz_session("subject", {"redirect_uri": "https://example.com"})
27 | assert tok["aud"] == "https://example.com"
28 | assert tok["sub"] == "subject"
29 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | A Python OpenID Connect implementation
2 | ======================================
3 |
4 | This is a complete implementation of OpenID Connect as specified in the `OpenID
5 | Connect Core specification`_. And as a side effect, a complete implementation
6 | of OAuth2.0 too.
7 |
8 | .. _OpenID Connect Core specification: http://openid.net/specs/openid-connect-core-1_0.html
9 |
10 | Getting a copy is simple with Pip_:
11 |
12 | .. _Pip: http://pip.pypa.io/
13 |
14 | ::
15 |
16 | $ pip install oic
17 |
18 | .. toctree::
19 | :maxdepth: 1
20 |
21 | examples/op
22 | examples/rp
23 | examples/cookbook
24 | examples/docker
25 | examples/tls
26 |
27 | contrib/install
28 | contrib/settings
29 | contrib/testing
30 | contrib/documentation
31 |
32 | .. raw:: html
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/doc/contrib/testing.rst:
--------------------------------------------------------------------------------
1 | .. _testing:
2 |
3 | Testing
4 | #######
5 |
6 | Using Pytest
7 | ------------
8 |
9 | Please make sure you have already reviewed the :ref:`install`.
10 |
11 | PyOIDC uses Pytest_ for testing.
12 |
13 | .. _Pytest: https://doc.pytest.org/
14 |
15 | You can install it along with the rest of the test dependencies via Pip_:
16 |
17 | .. _Pip: pip.pypa.io/en/stable/installing/
18 |
19 | ::
20 |
21 | $ pip install .[testing]
22 |
23 | Now, you can run the tests by simply invoking ``py.test``:
24 |
25 | ::
26 |
27 | $ py.test
28 |
29 | Using Tox
30 | ---------
31 |
32 | PyOIDC also uses Tox_ for testing. This is to ensure PyOIDC is supported across
33 | many versions of Python. You can install it via Pip_:
34 |
35 | .. _Tox: https://tox.readthedocs.io/
36 | .. _Pip: pip.pypa.io/en/stable/installing/
37 |
38 | ::
39 |
40 | $ pip install tox
41 |
42 | Then, check the available environments with:
43 |
44 | ::
45 |
46 | $ tox -l
47 |
48 | Then run Tox on your chosen environment:
49 |
50 | ::
51 |
52 | $ tox -e py36
53 |
--------------------------------------------------------------------------------
/oauth_example/as/htdocs/login.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 | <%def name="title()">Log in%def>
3 |
4 |
31 |
--------------------------------------------------------------------------------
/oidc_example/op2/templates/base.mako:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | <%block name="meta"/>
8 |
9 | <%block name="script"/>
10 |
11 | <%block name="css"/>
12 | <%block name="title"/>
13 |
14 |
15 |
16 | <%block name="header">
17 |
18 |
19 |
20 | <%block name="headline">%block>
21 |
22 |
23 | %block>
24 |
25 | ${self.body()}
26 |
27 | <%block name="footer">
28 |
29 |
30 | %block>
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/oidc_example/op3/Templates/base.mako:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | <%block name="meta"/>
8 |
9 | <%block name="script"/>
10 |
11 | <%block name="css"/>
12 | <%block name="title"/>
13 |
14 |
15 |
16 | <%block name="header">
17 |
18 |
19 |
20 | <%block name="headline">%block>
21 |
22 |
23 | %block>
24 |
25 | ${self.body()}
26 |
27 | <%block name="footer">
28 |
29 |
30 | %block>
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/tests/data/templates/root.mako:
--------------------------------------------------------------------------------
1 | <% self.seen_css = set() %>
2 | <%def name="css_link(path, media='')" filter="trim">
3 | % if path not in self.seen_css:
4 |
5 | % endif
6 | <% self.seen_css.add(path) %>
7 | %def>
8 | <%def name="css()" filter="trim">
9 | ${css_link('/css/main.css', 'screen')}
10 | %def>
11 | <%def name="pre()" filter="trim">
12 | %def>
13 | <%def name="post()" filter="trim">
14 |
15 |
18 |
19 | %def>
20 | ##
22 |
23 | OpenID Connect provider example
24 | ${self.css()}
25 |
26 |
27 |
28 | ${pre()}
29 | ## ${comps.dict_to_table(pageargs)}
30 | ##
31 | ${next.body()}
32 | ${post()}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/docker/op/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 | RUN apt-get update && apt-get install -y --no-install-recommends \
5 | ca-certificates \
6 | git \
7 | gnupg \
8 | ntp \
9 | wget
10 | RUN wget -q https://deb.nodesource.com/setup_12.x -O - | bash -
11 | RUN apt-get update && apt-get install -y --no-install-recommends \
12 | apache2 \
13 | nodejs && apt-get clean && rm -rf /var/lib/apt/lists/*
14 |
15 | ENV SRCDIR /usr/local/src
16 | ENV INSTDIR node-oidc-provider
17 | ENV SUBDIR ${SRCDIR}/${INSTDIR}
18 |
19 | WORKDIR ${SRCDIR}
20 | RUN git clone --depth=1 --branch=v6.17.3 https://github.com/panva/node-oidc-provider.git
21 | WORKDIR ${INSTDIR}
22 | RUN npm install
23 |
24 | COPY docker/op/apache-ssl.conf /etc/apache2/sites-available/ssl.conf
25 | COPY docker/op/cert.pem /etc/apache2/
26 | COPY docker/op/key.pem /etc/apache2/
27 |
28 | RUN a2enmod headers && a2enmod ssl && a2enmod proxy && a2enmod proxy_http && a2ensite ssl
29 |
30 | COPY docker/op/run.sh ${SUBDIR}/
31 |
32 | WORKDIR ${SUBDIR}
33 | ENTRYPOINT ["./run.sh"]
34 |
--------------------------------------------------------------------------------
/oidc_example/op2/templates/root.mako:
--------------------------------------------------------------------------------
1 | <% self.seen_css = set() %>
2 | <%def name="css_link(path, media='')" filter="trim">
3 | % if path not in self.seen_css:
4 |
5 | % endif
6 | <% self.seen_css.add(path) %>
7 | %def>
8 | <%def name="css()" filter="trim">
9 | ${css_link('/css/main.css', 'screen')}
10 | %def>
11 | <%def name="pre()" filter="trim">
12 | %def>
13 | <%def name="post()" filter="trim">
14 |
15 |
18 |
19 | %def>
20 | ##
22 |
23 | OpenID Connect provider example
24 | ${self.css()}
25 |
26 |
27 |
28 | ${pre()}
29 | ## ${comps.dict_to_table(pageargs)}
30 | ##
31 | ${next.body()}
32 | ${post()}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/oidc_example/op3/Templates/root.mako:
--------------------------------------------------------------------------------
1 | <% self.seen_css = set() %>
2 | <%def name="css_link(path, media='')" filter="trim">
3 | % if path not in self.seen_css:
4 |
5 | % endif
6 | <% self.seen_css.add(path) %>
7 | %def>
8 | <%def name="css()" filter="trim">
9 | ${css_link('/css/main.css', 'screen')}
10 | %def>
11 | <%def name="pre()" filter="trim">
12 | %def>
13 | <%def name="post()" filter="trim">
14 |
15 |
18 |
19 | %def>
20 | ##
22 |
23 | OpenID Connect provider example
24 | ${self.css()}
25 |
26 |
27 |
28 | ${pre()}
29 | ## ${comps.dict_to_table(pageargs)}
30 | ##
31 | ${next.body()}
32 | ${post()}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/oidc_example/op2/htdocs/javascript_login.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 | <%def name="title()">Log in%def>
3 |
4 |
22 |
23 |
26 |
27 | <%def name="add_js()">
28 |
33 | %def>
34 |
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/javascript_login.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 | <%def name="title()">Log in%def>
3 |
4 |
22 |
23 |
26 |
27 | <%def name="add_js()">
28 |
33 | %def>
34 |
--------------------------------------------------------------------------------
/tests/data/keys/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC3zCCAcegAwIBAgIBATANBgkqhkiG9w0BAQUFADA0MRgwFgYDVQQDEw9UaGUg
3 | Y29kZSB0ZXN0ZXIxGDAWBgNVBAoTD1VtZWEgVW5pdmVyc2l0eTAeFw0xMjA4MjEx
4 | MTAyMjFaFw0xMzA4MjExMTAyMjFaMDIxCzAJBgNVBAYTAlNFMSMwIQYDVQQDExpP
5 | cGVuSUQgQ29ubmVjdCBUZXN0IFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEP
6 | ADCCAQoCggEBANRAq0lVRsRw4wpvoC3RqEzwk3iIE0b4p9HBPTOrPxpA9LWt08ug
7 | wpbvBogZpfj0H0LUsmuRM7/BLlF4RYTQqUft/7zMFI2Cwcx+cmwAfzQUS/DCdTO1
8 | lM5vlkp5dYXWDKJV9cctnMtlJubGiLbmzDjYYVRvoRQLMsvYgg1/hVfGp6zj6Qgb
9 | mCtQdAWgUmnzA7rN0kfsavE+i4E3pcK97KyZukOgNgM3QbApJvlnClud+ApUWzGH
10 | zGiUJQWKZrZ0Lf5PHLVFl9ZP5CACexkeVof++eecAnFSW56HOIjYD7NSsjX5h79k
11 | YhK9pX9AZsaZM1BpzUDWjlagdfw9coLDTAMCAwEAATANBgkqhkiG9w0BAQUFAAOC
12 | AQEAIeLXKI+XukIcWHY67N9NqdWWhBi8HIygbvt6bNOlM9dFIBvc68LQIZSrJd/6
13 | AKs07N+mY9rewYFcORrgI6767Gd/vzu+HhEMpFgJnipPjBq6XuwzLSOPRHIOGMcx
14 | gLmHa/ALDhQq+ma4eghpxjYM4hY8VOXPRLzGE+WqOFc/PTUIxDRT5yk0ct+XlCdC
15 | mCRA9BnJfYG2ABsf2GtfNK2aXMIbCC/n9c/NNkffc2aXGImalj18BZzYW8TWNQt9
16 | Ypx4GMUpDZu8CLaddGHoAxZgar6+BLSwO8FWB5XiFLOH/OEai9o+LZZbSebL4fyl
17 | yST8CMkOK8hBl1tHmEWbknlH5A==
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------
/oidc_example/op2/cp_keys/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC3zCCAcegAwIBAgIBATANBgkqhkiG9w0BAQUFADA0MRgwFgYDVQQDEw9UaGUg
3 | Y29kZSB0ZXN0ZXIxGDAWBgNVBAoTD1VtZWEgVW5pdmVyc2l0eTAeFw0xMjA4MjEx
4 | MTAyMjFaFw0xMzA4MjExMTAyMjFaMDIxCzAJBgNVBAYTAlNFMSMwIQYDVQQDExpP
5 | cGVuSUQgQ29ubmVjdCBUZXN0IFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEP
6 | ADCCAQoCggEBANRAq0lVRsRw4wpvoC3RqEzwk3iIE0b4p9HBPTOrPxpA9LWt08ug
7 | wpbvBogZpfj0H0LUsmuRM7/BLlF4RYTQqUft/7zMFI2Cwcx+cmwAfzQUS/DCdTO1
8 | lM5vlkp5dYXWDKJV9cctnMtlJubGiLbmzDjYYVRvoRQLMsvYgg1/hVfGp6zj6Qgb
9 | mCtQdAWgUmnzA7rN0kfsavE+i4E3pcK97KyZukOgNgM3QbApJvlnClud+ApUWzGH
10 | zGiUJQWKZrZ0Lf5PHLVFl9ZP5CACexkeVof++eecAnFSW56HOIjYD7NSsjX5h79k
11 | YhK9pX9AZsaZM1BpzUDWjlagdfw9coLDTAMCAwEAATANBgkqhkiG9w0BAQUFAAOC
12 | AQEAIeLXKI+XukIcWHY67N9NqdWWhBi8HIygbvt6bNOlM9dFIBvc68LQIZSrJd/6
13 | AKs07N+mY9rewYFcORrgI6767Gd/vzu+HhEMpFgJnipPjBq6XuwzLSOPRHIOGMcx
14 | gLmHa/ALDhQq+ma4eghpxjYM4hY8VOXPRLzGE+WqOFc/PTUIxDRT5yk0ct+XlCdC
15 | mCRA9BnJfYG2ABsf2GtfNK2aXMIbCC/n9c/NNkffc2aXGImalj18BZzYW8TWNQt9
16 | Ypx4GMUpDZu8CLaddGHoAxZgar6+BLSwO8FWB5XiFLOH/OEai9o+LZZbSebL4fyl
17 | yST8CMkOK8hBl1tHmEWbknlH5A==
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------
/oidc_example/op3/static/jwks.json:
--------------------------------------------------------------------------------
1 | {"keys": [{"use": "enc", "n": "6LC5Zr1Ng3HN_RF173gSAtcWo3RbnRc-YtE2BZnmNDVe2cepFmMjYbcum6bonS7JWCTDYd5m0Gt7-yh71YQxF3bjXAEXGbR6w1405emJuurFgfAnwk8h-o__-DYoF4E9WdbHfi9wRa7tS8pAB2o1JpsH1r3O7wCSPb_cDRIQZ3R5ORjl-q_PWUFxAjLKe2IAM2rfJulertITnGlxcnzzy9cnIyYgY-gm17hZFZd1qLpNG10McyzlwxPl6c-7PagS2nx9Mdv4gUvaNwzgkzQQh9viJfBggc1o86CEPg8RAOqWjUJ8jHAYJDeRxEFHKGcbOXa2n1ZOBj-FHprIOg60Xw", "e": "AQAB", "kty": "RSA", "kid": "op0"}, {"use": "sig", "n": "6LC5Zr1Ng3HN_RF173gSAtcWo3RbnRc-YtE2BZnmNDVe2cepFmMjYbcum6bonS7JWCTDYd5m0Gt7-yh71YQxF3bjXAEXGbR6w1405emJuurFgfAnwk8h-o__-DYoF4E9WdbHfi9wRa7tS8pAB2o1JpsH1r3O7wCSPb_cDRIQZ3R5ORjl-q_PWUFxAjLKe2IAM2rfJulertITnGlxcnzzy9cnIyYgY-gm17hZFZd1qLpNG10McyzlwxPl6c-7PagS2nx9Mdv4gUvaNwzgkzQQh9viJfBggc1o86CEPg8RAOqWjUJ8jHAYJDeRxEFHKGcbOXa2n1ZOBj-FHprIOg60Xw", "e": "AQAB", "kty": "RSA", "kid": "op1"}, {"use": "sig", "crv": "P-256", "kty": "EC", "y": "SDi5lkPJ6OTf2uNTNlDuSNwmmsxtY6QQyOS7P5erMPo", "x": "I9NTB0qqgS1B5CkuKoZDTWbk7G4j6TZqBusrAtHNKro", "kid": "op2"}, {"use": "enc", "crv": "P-256", "kty": "EC", "y": "_F7JXiEvUPM8upu4J_q9MXhGAYLJ_CdzKg9REuV9Tbo", "x": "mbJogROQtkoPxauwEhnUfFGTmWWS6ps9GW-REM_5UgE", "kid": "op3"}]}
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/cp_keys/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC3zCCAcegAwIBAgIBATANBgkqhkiG9w0BAQUFADA0MRgwFgYDVQQDEw9UaGUg
3 | Y29kZSB0ZXN0ZXIxGDAWBgNVBAoTD1VtZWEgVW5pdmVyc2l0eTAeFw0xMjA4MjEx
4 | MTAyMjFaFw0xMzA4MjExMTAyMjFaMDIxCzAJBgNVBAYTAlNFMSMwIQYDVQQDExpP
5 | cGVuSUQgQ29ubmVjdCBUZXN0IFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEP
6 | ADCCAQoCggEBANRAq0lVRsRw4wpvoC3RqEzwk3iIE0b4p9HBPTOrPxpA9LWt08ug
7 | wpbvBogZpfj0H0LUsmuRM7/BLlF4RYTQqUft/7zMFI2Cwcx+cmwAfzQUS/DCdTO1
8 | lM5vlkp5dYXWDKJV9cctnMtlJubGiLbmzDjYYVRvoRQLMsvYgg1/hVfGp6zj6Qgb
9 | mCtQdAWgUmnzA7rN0kfsavE+i4E3pcK97KyZukOgNgM3QbApJvlnClud+ApUWzGH
10 | zGiUJQWKZrZ0Lf5PHLVFl9ZP5CACexkeVof++eecAnFSW56HOIjYD7NSsjX5h79k
11 | YhK9pX9AZsaZM1BpzUDWjlagdfw9coLDTAMCAwEAATANBgkqhkiG9w0BAQUFAAOC
12 | AQEAIeLXKI+XukIcWHY67N9NqdWWhBi8HIygbvt6bNOlM9dFIBvc68LQIZSrJd/6
13 | AKs07N+mY9rewYFcORrgI6767Gd/vzu+HhEMpFgJnipPjBq6XuwzLSOPRHIOGMcx
14 | gLmHa/ALDhQq+ma4eghpxjYM4hY8VOXPRLzGE+WqOFc/PTUIxDRT5yk0ct+XlCdC
15 | mCRA9BnJfYG2ABsf2GtfNK2aXMIbCC/n9c/NNkffc2aXGImalj18BZzYW8TWNQt9
16 | Ypx4GMUpDZu8CLaddGHoAxZgar6+BLSwO8FWB5XiFLOH/OEai9o+LZZbSebL4fyl
17 | yST8CMkOK8hBl1tHmEWbknlH5A==
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------
/tests/test_authn_user.py:
--------------------------------------------------------------------------------
1 | import base64
2 | from urllib.parse import quote_plus
3 |
4 | import pytest
5 |
6 | from oic.exception import ImproperlyConfigured
7 | from oic.utils.authn.user import BasicAuthn
8 | from oic.utils.authn.user import SymKeyAuthn
9 |
10 |
11 | def test_symkeyauthn_improperly_configured(provider):
12 | improper_symkey = ""
13 | with pytest.raises(ImproperlyConfigured) as err:
14 | SymKeyAuthn(srv=provider, ttl=666, symkey=improper_symkey)
15 | expected_msg = "SymKeyAuthn.symkey cannot be an empty value"
16 | assert expected_msg in str(err.value)
17 |
18 |
19 | def test_basic_authn_authenticate_as():
20 | pwd_database = {"Diana": "Piano player", "NonAscii": "€&+%#@äää"}
21 | ba = BasicAuthn(None, pwd=pwd_database)
22 |
23 | for user, passwd in pwd_database.items():
24 | credentials = "{}:{}".format(quote_plus(user), quote_plus(passwd))
25 |
26 | authz = base64.b64encode(credentials.encode("utf-8")).decode("utf-8")
27 | authorization_string = "Basic {}".format(authz)
28 |
29 | uid, when = ba.authenticated_as(authorization=authorization_string)
30 | assert uid == {"uid": user}
31 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/users.json:
--------------------------------------------------------------------------------
1 | {
2 | "diana": {
3 | "sub": "dikr0001",
4 | "name": "Diana Krall",
5 | "given_name": "Diana",
6 | "family_name": "Krall",
7 | "nickname": "Dina",
8 | "email": "diana@example.org",
9 | "email_verified": false,
10 | "phone_number": "+46 90 7865000",
11 | "address": {
12 | "street_address": "Umeå Universitet",
13 | "locality": "Umeå",
14 | "postal_code": "SE-90187",
15 | "country": "Sweden"
16 | }
17 | },
18 | "babs": {
19 | "sub": "babs0001",
20 | "name": "Barbara J Jensen",
21 | "given_name": "Barbara",
22 | "family_name": "Jensen",
23 | "nickname": "babs",
24 | "email": "babs@example.com",
25 | "email_verified": true,
26 | "address": {
27 | "street_address": "100 Universal City Plaza",
28 | "locality": "Hollywood",
29 | "region": "CA",
30 | "postal_code": "91608",
31 | "country": "USA"
32 | }
33 | },
34 | "upper": {
35 | "sub": "uppe0001",
36 | "name": "Upper Crust",
37 | "given_name": "Upper",
38 | "family_name": "Crust",
39 | "email": "uc@example.com",
40 | "email_verified": true
41 | }
42 | }
--------------------------------------------------------------------------------
/oauth_example/rp/htdocs/as_choice.mako:
--------------------------------------------------------------------------------
1 | <%!
2 | def as_choice(as_list):
3 | """
4 | Creates a dropdown list of authorization servers
5 | """
6 | element = ""
10 | return element
11 | %>
12 |
13 |
14 |
15 | OAuth2 RP Example
16 |
17 |
18 |
21 |
22 |
23 |
24 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | """Pytest fixtures for testing."""
2 | from typing import Any
3 | from typing import Dict
4 |
5 | import pytest
6 |
7 | from oic.oic.provider import Provider
8 | from oic.utils.authn.client import verify_client
9 | from oic.utils.authz import AuthzHandling
10 | from oic.utils.sdb import create_session_db
11 |
12 |
13 | @pytest.fixture
14 | def session_db_factory():
15 | def fac(issuer):
16 | return create_session_db(issuer, secret="supersecret", password="badpassword")
17 |
18 | return fac
19 |
20 |
21 | @pytest.fixture
22 | def session_db(session_db_factory):
23 | return session_db_factory("https://op.example.com")
24 |
25 |
26 | @pytest.fixture
27 | def provider(session_db):
28 | issuer = "https://op.example.com"
29 | client_db: Dict[str, Any] = {}
30 | verification_function = verify_client
31 | authz_handler = AuthzHandling()
32 | symkey = None
33 | user_info_store = None
34 | authn_broker = None
35 | return Provider(
36 | issuer,
37 | session_db,
38 | client_db,
39 | authn_broker,
40 | user_info_store,
41 | authz_handler,
42 | verification_function,
43 | symkey,
44 | )
45 |
--------------------------------------------------------------------------------
/oidc_example/README.md:
--------------------------------------------------------------------------------
1 | # Simple RP and OP examples
2 |
3 | These 2 examples can run on the same machine together following these steps.
4 |
5 | Both servers "use" up a port, and running them on the same machine means they
6 | need their own ports. `simple_rp` supports providing a response url with a port
7 | in it, so that will run on a random port (8000 in the example below) and
8 | `simple_op` runs on port 443 - the standard https port.
9 |
10 | Run the following:
11 |
12 | 1. Install oic from source using `python setup.py install`
13 | 1. Install `requirements.txt` for `simple_op` using `pip install -r requirements.txt`
14 | 1. Install `requirements.txt` for `simple_rp` using `pip install -r requirements.txt`
15 | 1. Start the op server on port 443 in `simple_op` using `python src/run.py settings.yaml.example -p 443`
16 | 1. Start the rp server on port 8000 in `simple_rp` using `python src/rp.py settings.yaml.example -p 8000`
17 | 1. Open the rp server in a browser,
18 | 1. Enter the uid `localhost` to connect to the simple op server
19 | 1. Login using the credentials in `simple_op/passwd.json` (this is referenced in the simple op example settings)
20 | 1. Observe the user info is loaded by the RP server
21 |
--------------------------------------------------------------------------------
/src/oic/utils/__init__.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import traceback
3 |
4 | __author__ = "rohe0002"
5 |
6 |
7 | def tobytes(value) -> bytes:
8 | """Convert value to bytes."""
9 | if isinstance(value, bytes):
10 | return value
11 | else:
12 | if isinstance(value, str):
13 | return value.encode()
14 | else:
15 | return bytes(value)
16 |
17 |
18 | def exception_trace(tag, exc, log=None):
19 | message = traceback.format_exception(*sys.exc_info())
20 | if log:
21 | log.error("[%s] ExcList: %s", tag, "".join(message))
22 | log.error("[%s] Exception: %s", tag, exc)
23 | else:
24 | print("[{0}] ExcList: {1}".format(tag, "".join(message)), file=sys.stderr)
25 | print("[{0}] Exception: {1}".format(tag, exc), file=sys.stderr)
26 |
27 |
28 | SORT_ORDER = {"RS": 0, "ES": 1, "HS": 2, "PS": 3, "no": 4}
29 |
30 |
31 | def sort_sign_alg(alg1, alg2):
32 | if SORT_ORDER[alg1[0:2]] < SORT_ORDER[alg2[0:2]]:
33 | return -1
34 | elif SORT_ORDER[alg1[0:2]] > SORT_ORDER[alg2[0:2]]:
35 | return 1
36 | else:
37 | if alg1 < alg2:
38 | return -1
39 | elif alg1 > alg2:
40 | return 1
41 | else:
42 | return 0
43 |
--------------------------------------------------------------------------------
/docker/integration_tests/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #TRAVIS and CI variables make the test suite think that it's running in a travis pipeline
4 | #which makes it start puppeteer with the --no-sandbox option, otherwise you get a no usable
5 | #sandbox error from chrome and it won't start
6 | export TRAVIS=TRAVIS
7 | export CI=CI
8 |
9 | export TEST_PORT=60003
10 | export TEST_HOSTNAME=op-test
11 | export TEST_PROTOCOL=https
12 | export TAG=default
13 | export NODE_TLS_REJECT_UNAUTHORIZED=0
14 |
15 | cd /root/oidc-provider-conformance-tests
16 | export ISSUER=https://op:4433
17 | echo "---Running oidc-provider-conformance-tests 'code' and 'id_token'---"
18 | concurrently -- "npm:code" "npm:id_token" || exit
19 | echo "---Running oidc-provider-conformance-tests 'id_token+token' and 'code+id_token'---"
20 | concurrently -- "npm:id_token+token" "npm:code+id_token" || exit
21 | echo "---Running oidc-provider-conformance-tests 'code+id_token+token' and 'code+token'---"
22 | concurrently -- "npm:code+id_token+token" "npm:code+token" || exit
23 |
24 | cd /root/openid-client-conformance-tests
25 | export ISSUER=https://rp-test:8080
26 | export NODE_TLS_REJECT_UNAUTHORIZED=0
27 | echo "---Running openid-client-conformance-tests---"
28 | npm run test || exit
29 | echo "---FINISHED---"
30 |
--------------------------------------------------------------------------------
/docker/rp_test/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 | ENV SRCDIR /usr/local/src
5 | ENV INSTDIR oidf
6 | ENV SUBDIR ${SRCDIR}/${INSTDIR}/oidc_cp_rplib
7 |
8 | RUN apt-get update && apt-get install -y --no-install-recommends \
9 | build-essential \
10 | git \
11 | libffi-dev \
12 | libssl-dev \
13 | python3-dev \
14 | python3-pip \
15 | python3-setuptools && apt-get clean && rm -rf /var/lib/apt/lists/*
16 |
17 | RUN python3 -mpip install -U pip setuptools
18 | RUN git clone --depth=1 https://github.com/openid-certification/otest.git ${SRCDIR}/otest
19 | WORKDIR ${SRCDIR}/otest
20 | RUN python3 setup.py install
21 |
22 | RUN git clone --depth=1 https://github.com/openid-certification/oidctest.git ${SRCDIR}/oidctest
23 | WORKDIR ${SRCDIR}/oidctest
24 | RUN python3 setup.py install
25 |
26 | WORKDIR ${SRCDIR}
27 | RUN oidc_setup.py ${SRCDIR}/oidctest ${INSTDIR}
28 | COPY docker/rp_test/cert.pem ${SUBDIR}/certs/
29 | COPY docker/rp_test/key.pem ${SUBDIR}/certs/
30 | COPY docker/rp_test/conf.py ${SUBDIR}/
31 | COPY docker/rp_test/run.sh ${SUBDIR}/
32 |
33 | RUN mkdir pyoidc
34 | COPY . ${SRCDIR}/pyoidc/
35 | WORKDIR ${SRCDIR}/pyoidc
36 | RUN python3 setup.py install
37 |
38 | WORKDIR ${SUBDIR}
39 | ENTRYPOINT ["./run.sh"]
40 |
--------------------------------------------------------------------------------
/docker/integration_tests/Makefile:
--------------------------------------------------------------------------------
1 | IMAGENAME?=oidctest-local-it
2 | CONTAINERNAME?=oidctest-it
3 |
4 | .PHONY: help
5 | help:
6 | @echo "Usage"
7 | @echo " build : Build the image"
8 | @echo " delete : Deletes the container"
9 | @echo " logs : Shows container logs"
10 | @echo " shell : Starts interactive shell"
11 | @echo " start : Starts the container (you need to run 'make build' once first)"
12 | @echo " status : Shows container status"
13 | @echo " stop : Stops the container"
14 | @echo " "
15 | @echo "Other oidctest containers must be already running when you start this container"
16 |
17 | .PHONY: build
18 | build:
19 | docker build -t "$(IMAGENAME)" .
20 | docker run --net=host --name "$(CONTAINERNAME)" -d "$(IMAGENAME)"
21 |
22 |
23 | .PHONY: start
24 | start:
25 | docker container start "$(CONTAINERNAME)"
26 | docker container logs --follow "$(CONTAINERNAME)"
27 |
28 | .PHONY: stop
29 | stop:
30 | docker stop "$(CONTAINERNAME)"
31 |
32 | .PHONY: delete
33 | delete:
34 | docker rm "$(CONTAINERNAME)"
35 |
36 | .PHONY: logs
37 | logs:
38 | docker container logs --follow "$(CONTAINERNAME)"
39 |
40 | .PHONY: shell
41 | shell:
42 | docker exec -it "$(CONTAINERNAME)" bash
43 |
44 | .PHONY: status
45 | status:
46 | docker ps -f name="$(CONTAINERNAME)"
47 |
--------------------------------------------------------------------------------
/docker/op_test/my_jwks_60003.json:
--------------------------------------------------------------------------------
1 | {"keys": [{"kty": "RSA", "use": "enc", "kid": "rJ2OTcGTyd1Gk1GHjX-0exXGpVLYC-f0wnhmApnIfDw", "n": "trHr6obGgLNQiOwgTqcRFl18QjREfixvocvQAM-iIzcWud1g86mJG8IHOmZfh6Q9MRUvToDU-y1b-p44AtFSwi3_j4dh6R99tSe_2J0QjHZ7by6_ujxo_4KwolDbb_ToON-0hgWw7q4nvtvEr0ajpeiVVbIcTjqi13kY8ZmkKN_HjLebqeu4nelsuxVLNwuFaXDwNqtynTNXrgQtOSDqCu7sadyfX5jC6FdnSCL1XRin2gVGbsJ_4QVOy3tfpxAZa5pwt347w-cOrRqrIFOr2oUAC3lW57xHq8XiwN5r4naziztHmsUY13Z20nr6-tgeR9IZayArCy3vzd_-PQHbEw", "e": "AQAB"}, {"kty": "RSA", "use": "sig", "kid": "r3kqK2g4_x6aZ_X_s5wN-HXFcuF4KkMWGXZATRLtdGU", "n": "y_HYxdN31Zkg-BRddSuUbNIvsZazg3f6T1aPKoiGKdhQ0zozho19n03_uDJOOMj9cZZzGQG-vABa9bVPOyuBYDxGNQJraUeMNC1MczeIDLmpSV_JtndrwT-RXsKE74eXTajdmtF-ovZ3to7N78zSgt4sivMwmj1z2LmjKZA6HS2dkUNdDGLg7u0gvQj9kvON-XMyG5gwpZnnlYmPhYLaLTEW6GV0MecjTeoUT50LKSqqdrsc7Cx4L5aIlJBJ34AWu3LlFVvacCJt7opgyR9OiXNdQPr_LalZzFHcJMsF1HUCb7F9L1l9xED67w6bkgzGEUCROhLYF3ItFNfh3Nsj5Q", "e": "AQAB"}, {"kty": "EC", "use": "sig", "kid": "0UxXvqg6eSWklYtiknLooQseuV8KDqo7nueEVK4J1qQ", "crv": "P-256", "x": "iUgt9gbOE0kmUowZ9qka5SqsWx-tDK64NE3AcjJQxo4", "y": "JlHv9cnk51XdlqoaFaFjxUOB7QQus1QTqvq_XwS_RCo"}, {"kty": "EC", "use": "enc", "kid": "lWMyG2VyQWlORh1_-wxg335hYUbxc5TIk0HrKAHoaEw", "crv": "P-256", "x": "aW0Wlzq1XZypiZkyUis7Lq1t1jZob6o-gzXldhkegQQ", "y": "wt2sgmId7ujsPmgQQlnpd1iXro4SGEPWwyR7yK5QYXw"}]}
--------------------------------------------------------------------------------
/tests/test_claims.py:
--------------------------------------------------------------------------------
1 | from oic.oic import claims_match
2 | from oic.utils.claims import ClaimsMode
3 |
4 |
5 | def test_claims_for_user():
6 | user = "foobar"
7 | user2mode = {user: "aggregate"}
8 | claims_mode = ClaimsMode(user2mode)
9 |
10 | assert claims_mode.aggregate(user)
11 |
12 |
13 | def test_claims_for_missing_user():
14 | claims_mode = ClaimsMode({})
15 |
16 | assert not claims_mode.aggregate("nobody")
17 |
18 |
19 | def test_non_aggregate_claims():
20 | user = "foobar"
21 | claims_mode = ClaimsMode({user: "distributed"})
22 |
23 | assert not claims_mode.aggregate(user)
24 |
25 |
26 | def test_claims_match():
27 | claims_request = {
28 | "sub": {"value": "248289761001"},
29 | "auth_time": {"essential": True},
30 | "acr": {
31 | "essential": True,
32 | "values": ["urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze"],
33 | },
34 | }
35 |
36 | assert claims_match("248289761001", claims_request["sub"])
37 | assert claims_match("123456789012", claims_request["sub"]) is False
38 | assert claims_match("123456789", claims_request["auth_time"])
39 | assert claims_match("urn:mace:incommon:iap:silver", claims_request["acr"])
40 | assert claims_match("urn:mace:incommon:iap:gold", claims_request["acr"]) is False
41 |
--------------------------------------------------------------------------------
/oidc_example/rp3/htdocs/rp_session_iframe.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/oidc_example/op2/htdocs/login_se.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | Logga in
4 |
5 |
6 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/login_se.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | Logga in
4 |
5 |
6 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/oidc_example/rp3/htdocs/opresult_repost.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OpenID Certification OP Test
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/oic/oauth2/exception.py:
--------------------------------------------------------------------------------
1 | from oic.exception import PyoidcError
2 |
3 | __author__ = "roland"
4 |
5 |
6 | class HttpError(PyoidcError):
7 | pass
8 |
9 |
10 | class MissingRequiredAttribute(PyoidcError):
11 | pass
12 |
13 |
14 | class VerificationError(PyoidcError):
15 | pass
16 |
17 |
18 | class ResponseError(PyoidcError):
19 | pass
20 |
21 |
22 | class TimeFormatError(PyoidcError):
23 | pass
24 |
25 |
26 | class CapabilitiesMisMatch(PyoidcError):
27 | pass
28 |
29 |
30 | class MissingEndpoint(PyoidcError):
31 | pass
32 |
33 |
34 | class TokenError(PyoidcError):
35 | pass
36 |
37 |
38 | class GrantError(PyoidcError):
39 | pass
40 |
41 |
42 | class ParseError(PyoidcError):
43 | pass
44 |
45 |
46 | class OtherError(PyoidcError):
47 | pass
48 |
49 |
50 | class NoClientInfoReceivedError(PyoidcError):
51 | pass
52 |
53 |
54 | class InvalidRequest(PyoidcError):
55 | pass
56 |
57 |
58 | class NonFatalException(PyoidcError):
59 | """
60 | Return the response but accompany it by an error message.
61 |
62 | :param resp: A response that the function/method would return on non-error
63 | :param msg: A message describing what error has occurred.
64 | """
65 |
66 | def __init__(self, resp, msg):
67 | self.resp = resp
68 | self.msg = msg
69 |
70 |
71 | class Unsupported(PyoidcError):
72 | pass
73 |
74 |
75 | class UnsupportedResponseType(Unsupported):
76 | pass
77 |
--------------------------------------------------------------------------------
/oidc_example/simple_op/src/provider/authn/user_pass.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from provider.authn import AuthnModule
4 | from provider.authn import make_cls_from_name
5 |
6 | from oic.utils.http_util import Response
7 |
8 |
9 | class UserPass(AuthnModule):
10 | url_endpoint = "/user_pass/verify"
11 |
12 | def __init__(self, db, template_env, template="user_pass.jinja2", **kwargs):
13 | super(UserPass, self).__init__(None)
14 | self.template_env = template_env
15 | self.template = template
16 |
17 | cls = make_cls_from_name(db["class"])
18 | self.user_db = cls(**db["kwargs"])
19 |
20 | self.kwargs = kwargs
21 | self.kwargs.setdefault("page_header", "Log in")
22 | self.kwargs.setdefault("user_label", "Username")
23 | self.kwargs.setdefault("passwd_label", "Password")
24 | self.kwargs.setdefault("submit_btn", "Log in")
25 |
26 | def __call__(self, *args, **kwargs):
27 | template = self.template_env.get_template(self.template)
28 | return Response(template.render(action=self.url_endpoint,
29 | state=json.dumps(kwargs),
30 | **self.kwargs))
31 |
32 | def verify(self, *args, **kwargs):
33 | username = kwargs["username"]
34 | if username in self.user_db and self.user_db[username] == kwargs[
35 | "password"]:
36 | return username, True
37 | else:
38 | return self.FAILED_AUTHN
39 |
--------------------------------------------------------------------------------
/src/oic/utils/userinfo/__init__.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | __author__ = "rolandh"
4 |
5 |
6 | class UserInfo(object):
7 | """Read only interface to a user info store."""
8 |
9 | def __init__(self, db=None):
10 | self.db = db
11 |
12 | def filter(self, userinfo, user_info_claims=None):
13 | """
14 | Return only those claims that are asked for.
15 |
16 | It's a best effort task; if essential claims are not present no error is flagged.
17 |
18 | :param userinfo: A dictionary containing the available user info.
19 | :param user_info_claims: A dictionary specifying the asked for claims
20 | :return: A dictionary of filtered claims.
21 | """
22 | if user_info_claims is None:
23 | return copy.copy(userinfo)
24 | else:
25 | result = {}
26 | missing = []
27 | optional = []
28 | for key, restr in user_info_claims.items():
29 | try:
30 | result[key] = userinfo[key]
31 | except KeyError:
32 | if restr == {"essential": True}:
33 | missing.append(key)
34 | else:
35 | optional.append(key)
36 | return result
37 |
38 | def __call__(self, userid, client_id, user_info_claims=None, **kwargs):
39 | try:
40 | return self.filter(self.db[userid], user_info_claims)
41 | except KeyError:
42 | return {}
43 |
--------------------------------------------------------------------------------
/tests/test_client_management.py:
--------------------------------------------------------------------------------
1 | # pylint: disable=redefined-outer-name, missing-docstring
2 |
3 | import json
4 | import tempfile
5 |
6 | import pytest
7 |
8 | from oic.utils.client_management import CDB
9 |
10 |
11 | @pytest.fixture
12 | def cdb():
13 | file = tempfile.NamedTemporaryFile() # just get a unique filename
14 | file.close()
15 | return CDB(file.name)
16 |
17 |
18 | class TestCDB(object):
19 | def test_create(self, cdb):
20 | info = self._create_new(cdb)
21 | assert info == cdb[info["client_id"]]
22 |
23 | def test_dump(self, cdb):
24 | info = self._create_new(cdb)
25 |
26 | file = tempfile.NamedTemporaryFile(delete=False)
27 | file.close()
28 | cdb.dump(file.name)
29 |
30 | with open(file.name) as f:
31 | from_file = json.load(f)
32 | assert from_file[0] == info # serialized to file properly
33 |
34 | client_id = info["client_id"]
35 | del cdb[client_id]
36 |
37 | with pytest.raises(KeyError):
38 | cdb[client_id] # make sure the client is removed
39 | cdb.load(file.name)
40 | assert cdb[client_id] == info # ensure the all info was restored
41 |
42 | def _create_new(self, client_db):
43 | info = client_db.create(
44 | ["https://example.com/redirect"],
45 | "https://example.com/policy",
46 | "https://example.com/logo",
47 | "https://example.com/jwks",
48 | )
49 |
50 | return info
51 |
--------------------------------------------------------------------------------
/oidc_example/op2/htdocs/login.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 |
5 |
36 |
37 | <%def name="add_js()">
38 |
43 | %def>
44 |
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/login.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 |
5 |
36 |
37 | <%def name="add_js()">
38 |
43 | %def>
44 |
--------------------------------------------------------------------------------
/tests/data/templates/login.mako:
--------------------------------------------------------------------------------
1 | <%inherit file="root.mako" />
2 |
5 |
36 |
37 | <%def name="add_js()">
38 |
43 | %def>
44 |
--------------------------------------------------------------------------------
/docker/op_test/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 | ENV SRCDIR /usr/local/src
5 | ENV INSTDIR oidf
6 | ENV SUBDIR ${SRCDIR}/${INSTDIR}/oidc_op
7 |
8 | RUN apt-get update && apt-get install -y --no-install-recommends \
9 | build-essential \
10 | git \
11 | libffi-dev \
12 | libssl-dev \
13 | python3-dev \
14 | python3-pip \
15 | python3-setuptools && apt-get clean && rm -rf /var/lib/apt/lists/*
16 |
17 | RUN python3 -mpip install -U pip setuptools
18 | RUN git clone --depth=1 https://github.com/openid-certification/otest.git ${SRCDIR}/otest
19 | WORKDIR ${SRCDIR}/otest
20 | RUN python3 setup.py install
21 |
22 | RUN git clone --depth=1 https://github.com/openid-certification/oidctest.git ${SRCDIR}/oidctest
23 | WORKDIR ${SRCDIR}/oidctest
24 | RUN python3 setup.py install
25 |
26 | WORKDIR ${SRCDIR}
27 | RUN oidc_setup.py ${SRCDIR}/oidctest ${INSTDIR}
28 | COPY docker/op_test/cert.pem ${SUBDIR}/certs/
29 | COPY docker/op_test/key.pem ${SUBDIR}/certs/
30 | COPY docker/op_test/config.py ${SUBDIR}/
31 | COPY docker/op_test/tt_config.py ${SUBDIR}/
32 | COPY docker/op_test/run.sh ${SUBDIR}/
33 |
34 | COPY docker/op_test/https%3A%2F%2Fop%3A4433 ${SUBDIR}/entities/https%3A%2F%2Fop%3A4433
35 | COPY docker/op_test/assigned_ports.json ${SUBDIR}/
36 | COPY docker/op_test/my_jwks_60003.json ${SUBDIR}/static/jwks_60003.json
37 |
38 | RUN mkdir pyoidc
39 | COPY . ${SRCDIR}/pyoidc
40 | WORKDIR ${SRCDIR}/pyoidc
41 | RUN python3 setup.py install
42 |
43 | WORKDIR ${SUBDIR}
44 | ENTRYPOINT ["./run.sh"]
45 |
--------------------------------------------------------------------------------
/docker/integration_tests/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 | RUN apt-get update && apt-get install -y --no-install-recommends\
5 | apache2 \
6 | ca-certificates \
7 | git \
8 | gnupg \
9 | libgconf-2-4 \
10 | libnss3-tools \
11 | ntp \
12 | wget \
13 | && apt-get clean \
14 | && rm -rf /var/lib/apt/lists/*
15 | RUN wget -q https://deb.nodesource.com/setup_12.x -O - | bash -
16 | RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
17 | RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list
18 | RUN apt-get update && apt-get install -y --no-install-recommends \
19 | google-chrome-stable \
20 | libxss1 \
21 | libxtst6 \
22 | nodejs \
23 | libgtk2.0-0 libgtk-3-0 libnotify-dev \
24 | libgconf-2-4 libnss3 libxss1 \
25 | libasound2 libxtst6 xauth xvfb \
26 | libgbm-dev \
27 | && apt-get clean \
28 | && rm -rf /var/lib/apt/lists/*
29 |
30 | WORKDIR /root
31 | RUN git clone https://github.com/openid-certification/oidc-provider-conformance-tests.git --depth 1
32 | WORKDIR /root/oidc-provider-conformance-tests
33 | RUN npm install --production
34 | WORKDIR /root
35 | RUN git clone https://github.com/openid-certification/openid-client-conformance-tests.git --depth 1
36 | WORKDIR /root/openid-client-conformance-tests
37 | RUN npm install --production
38 | RUN npm install -g concurrently@5
39 |
40 | COPY run.sh /root/run.sh
41 | RUN chmod 755 /root/run.sh
42 |
43 | ENTRYPOINT /root/run.sh
44 |
--------------------------------------------------------------------------------
/oidc_example/simple_rp/src/htdocs/repost_fragment.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | pyoidc RP
6 |
7 |
8 |
9 |
10 |
13 |
14 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/oidc_example/rp3/conf_heart.py:
--------------------------------------------------------------------------------
1 | # BASE = "https://lingon.ladok.umu.se"
2 | BASE = "https://localhost"
3 |
4 | # If BASE is https these has to be specified
5 | SERVER_CERT = "certs/server.crt"
6 | SERVER_KEY = "certs/server.key"
7 | CA_BUNDLE = None
8 | CERT_CHAIN = None
9 |
10 | VERIFY_SSL = False
11 |
12 | # information used when registering the client, this may be the same for all OPs
13 |
14 | ME = {
15 | "application_type": "web",
16 | "application_name": "idpproxy",
17 | "contacts": ["ops@example.com"],
18 | "redirect_uris": ["{base}authz_cb"],
19 | "post_logout_redirect_uris": ["{base}logout_success"],
20 | "response_types": ["code"],
21 | 'token_endpoint_auth_method': ['private_key_jwt']
22 | }
23 |
24 | BEHAVIOUR = {
25 | "response_type": "code",
26 | "scope": ["openid", "profile", "email", "address", "phone"],
27 | }
28 |
29 | ACR_VALUES = ["PASSWD"]
30 |
31 | # The keys in this dictionary are the OPs short userfriendly name
32 | # not the issuer (iss) name.
33 |
34 | CLIENTS = {
35 | # The ones that support webfinger, OP discovery and client registration
36 | # This is the default, any client that is not listed here is expected to
37 | # support dynamic discovery and registration.
38 | "": {
39 | "client_info": ME,
40 | "behaviour": BEHAVIOUR
41 | },
42 | }
43 |
44 | KEY_SPECIFICATION = [
45 | {"type": "RSA", "key": "keys/pyoidc_enc", "use": ["enc"]},
46 | {"type": "RSA", "key": "keys/pyoidc_sig", "use": ["sig"]},
47 | {"type": "EC", "crv": "P-256", "use": ["sig"]},
48 | {"type": "EC", "crv": "P-256", "use": ["enc"]}
49 | ]
50 |
51 | CLIENT_TYPE = 'OAUTH2' # one of OIDC/OAUTH2
52 | USERINFO = False
53 |
--------------------------------------------------------------------------------
/src/oic/__init__.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | import string
3 |
4 | # Since SystemRandom is not available on all systems
5 | try:
6 | # Python 3.6+, designed for this usecase
7 | from secrets import choice
8 | except ImportError:
9 | import random
10 |
11 | try:
12 | # Python 2.4+ if available on the platform
13 | _sysrand = random.SystemRandom()
14 | choice = _sysrand.choice
15 | except AttributeError:
16 | # Fallback, really bad
17 | import warnings
18 |
19 | choice = random.choice
20 | warnings.warn(
21 | "No good random number generator available on this platform. "
22 | "Security tokens will be weak and guessable.",
23 | RuntimeWarning,
24 | )
25 |
26 | __author__ = "Roland Hedberg"
27 | __version__ = "1.6.0"
28 |
29 |
30 | OIDCONF_PATTERN = "%s/.well-known/openid-configuration"
31 | CC_METHOD = {"S256": hashlib.sha256, "S384": hashlib.sha384, "S512": hashlib.sha512}
32 |
33 |
34 | def rndstr(size=16):
35 | """
36 | Return a string of random ascii characters or digits.
37 |
38 | :param size: The length of the string
39 | :return: string
40 | """
41 | _basech = string.ascii_letters + string.digits
42 | return "".join([choice(_basech) for _ in range(size)])
43 |
44 |
45 | BASECH = string.ascii_letters + string.digits + "-._~"
46 |
47 |
48 | def unreserved(size=64):
49 | """
50 | Return a string of random ascii characters, digits and unreserved characters for use as RFC 7636 code verifiers.
51 |
52 | :param size: The length of the string
53 | :return: string
54 | """
55 | return "".join([choice(BASECH) for _ in range(size)])
56 |
--------------------------------------------------------------------------------
/oidc_example/rp3/conf_heart.py.ex:
--------------------------------------------------------------------------------
1 | BASE = "https://localhost"
2 | #BASE = "https://130.239.200.165"
3 |
4 | # If BASE is https these has to be specified
5 | SERVER_CERT = "certs/server.crt"
6 | SERVER_KEY = "certs/server.key"
7 | CA_BUNDLE = None
8 | CERT_CHAIN = None
9 |
10 | VERIFY_SSL = False
11 |
12 | # information used when registering the client, this may be the same for all OPs
13 |
14 | ME = {
15 | "application_type": "web",
16 | "application_name": "idpproxy",
17 | "contacts": ["ops@example.com"],
18 | "redirect_uris": ["{base}authz_cb/{iss}"],
19 | "post_logout_redirect_uris": ["{base}logout_success/{iss}"],
20 | "response_types": ["code"],
21 | # 'token_endpoint_auth_method': ''
22 | }
23 |
24 | BEHAVIOUR = {
25 | "response_type": "code",
26 | "scope": ["offline_access"],
27 | }
28 |
29 | ACR_VALUES = []
30 |
31 | # The keys in then CLIENTS dictionary are the OPs short user friendly name
32 | # not the issuer (iss) name.
33 |
34 | CLIENTS = {
35 | # The ones that support web finger, OP discovery and dynamic client
36 | # registration.
37 | # This is the default, any client that is not specifically listed here is
38 | # expected to support dynamic discovery and registration.
39 | "": {
40 | "client_info": ME,
41 | "behaviour": BEHAVIOUR,
42 | 'config': {
43 | 'code_challenge': {
44 | 'length': 64,
45 | 'method': 'S256'
46 | }
47 | }
48 | },
49 | }
50 |
51 | USERINFO = False
52 | RESOURCE_SERVER = None
53 | CLIENT_TYPE = 'OAuth2'
54 |
55 | KEY_SPECIFICATION = [
56 | {"type": "RSA", "use": ["enc", "sig"]},
57 | {"type": "EC", "crv": "P-256", "use": ["enc", "sig"]},
58 | ]
59 |
--------------------------------------------------------------------------------
/tests/test_jwt.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from oic.utils.jwt import JWT
4 | from oic.utils.keyio import build_keyjar
5 | from oic.utils.keyio import keybundle_from_local_file
6 |
7 | __author__ = "roland"
8 |
9 |
10 | BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "data/keys"))
11 |
12 | keys = [
13 | {"type": "RSA", "key": os.path.join(BASE_PATH, "cert.key"), "use": ["enc", "sig"]},
14 | {"type": "EC", "crv": "P-256", "use": ["sig"]},
15 | {"type": "EC", "crv": "P-256", "use": ["enc"]},
16 | ]
17 | jwks, keyjar, kidd = build_keyjar(keys)
18 | issuer = "https://fedop.example.org"
19 |
20 |
21 | def _eq(l1, l2):
22 | return set(l1) == set(l2)
23 |
24 |
25 | def test_jwt_pack():
26 | _jwt = JWT(keyjar, lifetime=3600, iss=issuer).pack()
27 |
28 | assert _jwt
29 | assert len(_jwt.split(".")) == 3
30 |
31 |
32 | def test_jwt_pack_and_unpack():
33 | srv = JWT(keyjar, iss=issuer)
34 | _jwt = srv.pack(sub="sub")
35 |
36 | info = srv.unpack(_jwt)
37 |
38 | assert _eq(info.keys(), ["jti", "iat", "exp", "iss", "sub", "kid"])
39 |
40 |
41 | class TestJWT(object):
42 | """Tests for JWT."""
43 |
44 | def test_unpack_verify_key(self):
45 | srv = JWT(keyjar, iss=issuer)
46 | _jwt = srv.pack(sub="sub")
47 | # Remove the signing key from keyjar
48 | keyjar.remove_key("", "RSA", "")
49 | # And add it back as verify
50 | kb = keybundle_from_local_file(
51 | os.path.join(BASE_PATH, "cert.key"), "RSA", ["ver"]
52 | )
53 | # keybundle_from_local_file doesn'assign kid, so assign manually
54 | kb._keys[0].kid = kidd["sig"]["RSA"]
55 | keyjar.add_kb("", kb)
56 | info = srv.unpack(_jwt)
57 | assert info["sub"] == "sub"
58 |
--------------------------------------------------------------------------------
/oauth_example/as/authn_setup.py:
--------------------------------------------------------------------------------
1 | from oic.utils.authn.authn_context import AuthnBroker
2 |
3 | __author__ = "roland"
4 |
5 |
6 | def ldap_validation(config):
7 | from oic.utils.authn.ldap_member import UserLDAPMemberValidation
8 |
9 | config["args"].update(config["conf"])
10 | return UserLDAPMemberValidation(**config["args"])
11 |
12 |
13 | VALIDATOR = {"LDAP": ldap_validation}
14 |
15 |
16 | def cas_setup(item):
17 | from oic.utils.authn.user_cas import CasAuthnMethod
18 |
19 | try:
20 | v_cnf = item["validator"]
21 | except KeyError:
22 | _func = None
23 | else:
24 | _func = VALIDATOR[v_cnf["type"].upper()](item)
25 |
26 | _cnf = item["config"]
27 | return CasAuthnMethod(
28 | None, _cnf["cas_server"], item["URL"], _cnf["return_to"], _func
29 | )
30 |
31 |
32 | def userpwd_setup(item):
33 | from oic.utils.authn.user import UsernamePasswordMako
34 |
35 | _conf = item["config"]
36 | return UsernamePasswordMako(
37 | None, "login.mako", _conf["lookup"], _conf["passwd"], _conf["return_to"]
38 | )
39 |
40 |
41 | AUTH_METHOD = {
42 | "UserPassword": userpwd_setup,
43 | "CAS": cas_setup,
44 | }
45 |
46 |
47 | def authn_setup(config):
48 | broker = AuthnBroker()
49 |
50 | # Which methods to use is defined in the configuration file
51 | for authkey, method_conf in config.AUTHN_METHOD.items():
52 | try:
53 | func = AUTH_METHOD[authkey]
54 | except KeyError:
55 | pass
56 | else:
57 | broker.add(
58 | method_conf["ACR"],
59 | func(method_conf),
60 | method_conf["WEIGHT"],
61 | method_conf["URL"],
62 | )
63 |
64 | return broker
65 |
--------------------------------------------------------------------------------
/docker/op/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIErjCCApagAwIBAgIJAMBDTTEuAAmkMA0GCSqGSIb3DQEBCwUAMA0xCzAJBgNV
3 | BAMMAm9wMB4XDTE4MTAxMjA1MTA1N1oXDTE5MTAxMjA1MTA1N1owDTELMAkGA1UE
4 | AwwCb3AwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDDitqHIUI0sSBA
5 | BVig2d7z1Yu+1xpfeXxCwiMoaD1HMF+Mbqe1yKVc741TibwFv9WC+Nk/4jGdXfT+
6 | vt6zUiGb3/RuICEsfFE9nPfGH+/LdjGwguo/KOAckiOg450tPkg/bPpQ0OlJX7Co
7 | nwra4C6VveH53lk5Wrf/jtmQVezgWZCXly9PJ9h3nscxRy1ffvuDC+EOft02d8as
8 | 0jW/84xrP8ELhQoj8w2pUfyv4c/ZZj3vi/EPKM0DjgQWedz02loEwwCA2UVHFSiy
9 | qrEr0tiAOkmrXIgA/jhChaqUs2D7CM2vosUwkHgExU+bg0rmHUJgFDWih8TR29OI
10 | GxXy0T9pdtWPu4f2Ox4A4LSjzqMJwiTw9yHqFwixQSm4czLFq6WsJXx67UBGWL+o
11 | TyCnu0glPbEm3hQS6bjmzWyD8Gb4N3wyUJIu85/IaGRBBUqmlbH0sWn4cr2ax7hl
12 | YZbIdqTxLmcXA4XrjQ5gtAPv1CrWxqwivMnkyEYmuNbRd/ZQ5JaNYAmneADiPt7a
13 | i790HOX3+cAlm0ymDu5mgzOJ//mGZhY4dF75id/d+RX3xSf7FLd0OD4WSxPHjDPa
14 | zC7Dn+LpUzSNgTV4/vHwFIT880xRNIaAB+DS5pA1aLvFGfhzPoKKKns75KZ1Hh+t
15 | iTGL8xXKDfrCID0ECve0YvoCkz8GowIDAQABoxEwDzANBgNVHREEBjAEggJvcDAN
16 | BgkqhkiG9w0BAQsFAAOCAgEAfTU1yJa9xNcwUMdqnmsSyc7WAGlnVAtHaur5CmL2
17 | YzAT27E4oWei3rIyobrX6AMl8lU6fZot2yTxlx5c+e5GkgBWsQD50F6ePiLqaFoH
18 | hRAL03bqd6fczmWkJqi7ZzfA7bL6vYaE7CP/OcYnUP9lwOpXR/9sw6+68FYiUJV/
19 | iR0qLH+H5uCQlm7S1/VPLbVfnnSc1ZdOnMvWg/9gS0KOCBgZTe0Umx5Md9sk2kCZ
20 | 9HnHR7n9jLivAYzb+BthAGH+scTIVdXvBHU+xsV2vjw6nhdj7M0e5JAuquCjyTVG
21 | W0WtNTY6XnoW59nAfgsLc40HW5ZW40hcqD+Ag1yXnGaWGoYITUIIs3H8DVdRUw7m
22 | C5ktZNht/DRi7PTAMhMLt2IcEKSV2XvfJ5CHHUk+gG0HC19I5HitdeEC2cvWSo+Z
23 | UFTyreBDe6lNfhNKffY+o8IOtjq0BXaBBGTKZ9qXz9DILkxScoF6O4vsNFO4llJq
24 | OGr3lEC4W3ODGeyGdgoihUJjh/3iqqzV8m6wX0mx5Eeu2cd/SCU88u3VWPhqoffN
25 | bEI3GFgIWq8a79z9+BajuFsiYSVqmW9F88mwL2UyVLyxlbmvm5CHAaRcLZN5JC6C
26 | G9pQadRELZ4L/7VHem41xNvQNPikUv/JeTWQq3Y+imTt3FVPX4qmuYdWoznkILVF
27 | BTQ=
28 | -----END CERTIFICATE-----
29 |
--------------------------------------------------------------------------------
/tests/data/keys/cert.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA1ECrSVVGxHDjCm+gLdGoTPCTeIgTRvin0cE9M6s/GkD0ta3T
3 | y6DClu8GiBml+PQfQtSya5Ezv8EuUXhFhNCpR+3/vMwUjYLBzH5ybAB/NBRL8MJ1
4 | M7WUzm+WSnl1hdYMolX1xy2cy2Um5saItubMONhhVG+hFAsyy9iCDX+FV8anrOPp
5 | CBuYK1B0BaBSafMDus3SR+xq8T6LgTelwr3srJm6Q6A2AzdBsCkm+WcKW534ClRb
6 | MYfMaJQlBYpmtnQt/k8ctUWX1k/kIAJ7GR5Wh/7555wCcVJbnoc4iNgPs1KyNfmH
7 | v2RiEr2lf0BmxpkzUGnNQNaOVqB1/D1ygsNMAwIDAQABAoIBAQDUMOqMX5Jl5K01
8 | y66I3+avNHtZrkAHXaL4UYVL2FE3f+SklGj+U3L1zXPsMCf7IKL3/wd3/iuL8ibK
9 | D8EALFJvtIFMT4HkjuoL9AWT71M7z2a0BNOCpG9liazoO1DAQeNTjzgsrW7o7/Da
10 | GXSn1UgpNDjpXsfb7+4SWBp8QBYgTok/dx/nZyewZsVtkCsnwrm26Y2k8nhynLm1
11 | nGkQBbRKweQJ5O3PrsrZhRO9OXJ10WK/lYHVqRnu4dam8iP8JHKz5CQN/O7x0HI5
12 | VHHAl0Az4+YZe8wrdNhgtkkOhGxwOtIK5Q3eV8st51YBpWbMiDtQ53ghisWtyNzg
13 | EyphOksxAoGBAO1bTWHsuo6srY4cEJJlJ/C7W237iUM2p9MkeOwcewSXtgY19jAb
14 | IalYzn+yIHLqMyJ1H4cA1sBXBooNvkjVd+7niBbE8du2LyHf4avhNHN2tgKIOjpj
15 | GCsitLEqhyQmUUlYC3z8tQbh99b7fqn2kBDnhdSWPojEx84eXQ71IhMPAoGBAOTs
16 | lQ2iT3cqyore02YOieDwSg7n4flAPPG6cTGGQeOyHpNllTy9U/wyEBrHGGSCkjHI
17 | uDICHtYxyBmL6b0H5IyT4vn1Wxm19ecy8zbuK7Lmwd/iWRfKlGr+YQuez/mHVcCG
18 | YMoQvS6j8WOrQxt2wdOMNatgJeJSz66TaRy2QWfNAoGBAOmTWNJN8MSon15itdgq
19 | 3aQj6/SOfOR866h3ktvfpxu85C62eZ+bg4OwVf4J367WVB3LnovvQmYi/ddrcN8h
20 | 2xVqGV020D+DyFwQgnbvdvtNTg2t24dLryP70k8qZ7UmVAXWM+/6i3bLdmbENUCy
21 | 19Ea1XN/quhSpcFr1e37Q133AoGAD5GLXX8BWoBdf+5BgDpS5CpTTwo0EwhsXKAq
22 | XIzd5EdTzwBkktnpYUhiUf/iR8udd6dH55a/VB/UlPAv+DwWLf1MvWUTSf9W9t8/
23 | LSgrbqJE4x34oyaSy2f7X5fwWu76RPqekH9s7kQWAYo/KRn9eo6Zg8spKGgrWZsK
24 | 1foLHq0CgYBJRjKEY79aNuKCJZw60QPpXodJ65RJufXPz9MgDdoxUOtno8eYPfep
25 | KWWyhJsQXhMJNUMZGvQXRXaaZ3ZZp1e1q18CLh1TqbInC1ODW3L/ZAWCpT9ihcdA
26 | Owj1RL042er59qut/nivipmB5fn1hTbRDLq9rng0fsNU9XlrETbUfg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/oauth_example/as/keys/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA1ECrSVVGxHDjCm+gLdGoTPCTeIgTRvin0cE9M6s/GkD0ta3T
3 | y6DClu8GiBml+PQfQtSya5Ezv8EuUXhFhNCpR+3/vMwUjYLBzH5ybAB/NBRL8MJ1
4 | M7WUzm+WSnl1hdYMolX1xy2cy2Um5saItubMONhhVG+hFAsyy9iCDX+FV8anrOPp
5 | CBuYK1B0BaBSafMDus3SR+xq8T6LgTelwr3srJm6Q6A2AzdBsCkm+WcKW534ClRb
6 | MYfMaJQlBYpmtnQt/k8ctUWX1k/kIAJ7GR5Wh/7555wCcVJbnoc4iNgPs1KyNfmH
7 | v2RiEr2lf0BmxpkzUGnNQNaOVqB1/D1ygsNMAwIDAQABAoIBAQDUMOqMX5Jl5K01
8 | y66I3+avNHtZrkAHXaL4UYVL2FE3f+SklGj+U3L1zXPsMCf7IKL3/wd3/iuL8ibK
9 | D8EALFJvtIFMT4HkjuoL9AWT71M7z2a0BNOCpG9liazoO1DAQeNTjzgsrW7o7/Da
10 | GXSn1UgpNDjpXsfb7+4SWBp8QBYgTok/dx/nZyewZsVtkCsnwrm26Y2k8nhynLm1
11 | nGkQBbRKweQJ5O3PrsrZhRO9OXJ10WK/lYHVqRnu4dam8iP8JHKz5CQN/O7x0HI5
12 | VHHAl0Az4+YZe8wrdNhgtkkOhGxwOtIK5Q3eV8st51YBpWbMiDtQ53ghisWtyNzg
13 | EyphOksxAoGBAO1bTWHsuo6srY4cEJJlJ/C7W237iUM2p9MkeOwcewSXtgY19jAb
14 | IalYzn+yIHLqMyJ1H4cA1sBXBooNvkjVd+7niBbE8du2LyHf4avhNHN2tgKIOjpj
15 | GCsitLEqhyQmUUlYC3z8tQbh99b7fqn2kBDnhdSWPojEx84eXQ71IhMPAoGBAOTs
16 | lQ2iT3cqyore02YOieDwSg7n4flAPPG6cTGGQeOyHpNllTy9U/wyEBrHGGSCkjHI
17 | uDICHtYxyBmL6b0H5IyT4vn1Wxm19ecy8zbuK7Lmwd/iWRfKlGr+YQuez/mHVcCG
18 | YMoQvS6j8WOrQxt2wdOMNatgJeJSz66TaRy2QWfNAoGBAOmTWNJN8MSon15itdgq
19 | 3aQj6/SOfOR866h3ktvfpxu85C62eZ+bg4OwVf4J367WVB3LnovvQmYi/ddrcN8h
20 | 2xVqGV020D+DyFwQgnbvdvtNTg2t24dLryP70k8qZ7UmVAXWM+/6i3bLdmbENUCy
21 | 19Ea1XN/quhSpcFr1e37Q133AoGAD5GLXX8BWoBdf+5BgDpS5CpTTwo0EwhsXKAq
22 | XIzd5EdTzwBkktnpYUhiUf/iR8udd6dH55a/VB/UlPAv+DwWLf1MvWUTSf9W9t8/
23 | LSgrbqJE4x34oyaSy2f7X5fwWu76RPqekH9s7kQWAYo/KRn9eo6Zg8spKGgrWZsK
24 | 1foLHq0CgYBJRjKEY79aNuKCJZw60QPpXodJ65RJufXPz9MgDdoxUOtno8eYPfep
25 | KWWyhJsQXhMJNUMZGvQXRXaaZ3ZZp1e1q18CLh1TqbInC1ODW3L/ZAWCpT9ihcdA
26 | Owj1RL042er59qut/nivipmB5fn1hTbRDLq9rng0fsNU9XlrETbUfg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/oidc_example/op2/cp_keys/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA1ECrSVVGxHDjCm+gLdGoTPCTeIgTRvin0cE9M6s/GkD0ta3T
3 | y6DClu8GiBml+PQfQtSya5Ezv8EuUXhFhNCpR+3/vMwUjYLBzH5ybAB/NBRL8MJ1
4 | M7WUzm+WSnl1hdYMolX1xy2cy2Um5saItubMONhhVG+hFAsyy9iCDX+FV8anrOPp
5 | CBuYK1B0BaBSafMDus3SR+xq8T6LgTelwr3srJm6Q6A2AzdBsCkm+WcKW534ClRb
6 | MYfMaJQlBYpmtnQt/k8ctUWX1k/kIAJ7GR5Wh/7555wCcVJbnoc4iNgPs1KyNfmH
7 | v2RiEr2lf0BmxpkzUGnNQNaOVqB1/D1ygsNMAwIDAQABAoIBAQDUMOqMX5Jl5K01
8 | y66I3+avNHtZrkAHXaL4UYVL2FE3f+SklGj+U3L1zXPsMCf7IKL3/wd3/iuL8ibK
9 | D8EALFJvtIFMT4HkjuoL9AWT71M7z2a0BNOCpG9liazoO1DAQeNTjzgsrW7o7/Da
10 | GXSn1UgpNDjpXsfb7+4SWBp8QBYgTok/dx/nZyewZsVtkCsnwrm26Y2k8nhynLm1
11 | nGkQBbRKweQJ5O3PrsrZhRO9OXJ10WK/lYHVqRnu4dam8iP8JHKz5CQN/O7x0HI5
12 | VHHAl0Az4+YZe8wrdNhgtkkOhGxwOtIK5Q3eV8st51YBpWbMiDtQ53ghisWtyNzg
13 | EyphOksxAoGBAO1bTWHsuo6srY4cEJJlJ/C7W237iUM2p9MkeOwcewSXtgY19jAb
14 | IalYzn+yIHLqMyJ1H4cA1sBXBooNvkjVd+7niBbE8du2LyHf4avhNHN2tgKIOjpj
15 | GCsitLEqhyQmUUlYC3z8tQbh99b7fqn2kBDnhdSWPojEx84eXQ71IhMPAoGBAOTs
16 | lQ2iT3cqyore02YOieDwSg7n4flAPPG6cTGGQeOyHpNllTy9U/wyEBrHGGSCkjHI
17 | uDICHtYxyBmL6b0H5IyT4vn1Wxm19ecy8zbuK7Lmwd/iWRfKlGr+YQuez/mHVcCG
18 | YMoQvS6j8WOrQxt2wdOMNatgJeJSz66TaRy2QWfNAoGBAOmTWNJN8MSon15itdgq
19 | 3aQj6/SOfOR866h3ktvfpxu85C62eZ+bg4OwVf4J367WVB3LnovvQmYi/ddrcN8h
20 | 2xVqGV020D+DyFwQgnbvdvtNTg2t24dLryP70k8qZ7UmVAXWM+/6i3bLdmbENUCy
21 | 19Ea1XN/quhSpcFr1e37Q133AoGAD5GLXX8BWoBdf+5BgDpS5CpTTwo0EwhsXKAq
22 | XIzd5EdTzwBkktnpYUhiUf/iR8udd6dH55a/VB/UlPAv+DwWLf1MvWUTSf9W9t8/
23 | LSgrbqJE4x34oyaSy2f7X5fwWu76RPqekH9s7kQWAYo/KRn9eo6Zg8spKGgrWZsK
24 | 1foLHq0CgYBJRjKEY79aNuKCJZw60QPpXodJ65RJufXPz9MgDdoxUOtno8eYPfep
25 | KWWyhJsQXhMJNUMZGvQXRXaaZ3ZZp1e1q18CLh1TqbInC1ODW3L/ZAWCpT9ihcdA
26 | Owj1RL042er59qut/nivipmB5fn1hTbRDLq9rng0fsNU9XlrETbUfg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/oidc_example/op3/cryptography_keys/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA6LC5Zr1Ng3HN/RF173gSAtcWo3RbnRc+YtE2BZnmNDVe2cep
3 | FmMjYbcum6bonS7JWCTDYd5m0Gt7+yh71YQxF3bjXAEXGbR6w1405emJuurFgfAn
4 | wk8h+o//+DYoF4E9WdbHfi9wRa7tS8pAB2o1JpsH1r3O7wCSPb/cDRIQZ3R5ORjl
5 | +q/PWUFxAjLKe2IAM2rfJulertITnGlxcnzzy9cnIyYgY+gm17hZFZd1qLpNG10M
6 | cyzlwxPl6c+7PagS2nx9Mdv4gUvaNwzgkzQQh9viJfBggc1o86CEPg8RAOqWjUJ8
7 | jHAYJDeRxEFHKGcbOXa2n1ZOBj+FHprIOg60XwIDAQABAoIBAGbZgkFyp/nTCijz
8 | GE1OJavitUtvSXUwim80KOwl37Yw5ulc0pSmIkP1K2E6T7P2M6HFsiSmoIw8DhNw
9 | C/hO00IbVxhaFQNUHjUPhVMgPDQFxGIQLAq7Xnn5PztPeL4W7m6wvAG+5yGt1Y47
10 | 6bw9Shvzx223/OjwODOaA6I1W1HWNmHR3VO2+l7VTvNJ9I80u/PY3nvbRP5t2But
11 | NoepW6XBUnWytQTHbIia+8VpEJ4xQCLFTRSdGCCx/uH2qtCFM74tmEzBSYeQKbra
12 | vcdeMP0NMtz9u1wXpQzcU5xVWoN1lZaXU8X5njsrxTW+A+YRDCY5qyz0mjGCMDFR
13 | 05BgBq0CgYEA8yJ0bjl9uFLBDa8a01g9lDgFrKLA1SbnaTCd7B/K7Yw4XOmyWWzT
14 | NkVk5cIdn5XgMI2p9DuPlLp8VcBxrUeXKqWLenyWwj/O9aYYbtJ3mMG9Ew+z354a
15 | nh2BeyREA3kUFV9T62MAzgGoOLxmeki0Vg9QaNzNZ0TiXRTSgmhaOdUCgYEA9QDK
16 | IcLB2B8u3BDhKlqAi/x74DXwnWr+NH9yXcok17/CfdL65ohlq/8vn9iLIGPm21HD
17 | qElpY8VZ1SN47CbXCpBIYxUOAq1X4z6v2dpmia0wKX9DwGSNq1AjGv/q1XVZWP+L
18 | bwY9iYBtZkzQ6O6gFNYtahU863S1Y1wbl/dde2MCgYByeN5opxjSF+RdFPyEVR9p
19 | EZdaWKaBtPdvRzyTV8SrY0GGPWGDSQGIo9OFeYeJA3+yXICQRRqs48B2f00GUJaT
20 | ta2d1dsFShWfAryuMNmuSklDGDmQJ1hQ6YN0/vYmzHLwPRm90bcnRxB05f85w9Fk
21 | U4GAXbU30e7h9FPIomkYoQKBgQCRdQeMpbEqW9EZTFgyKgsZkSwGgF+7RfNoPaYr
22 | ssDO6oVQ6HqXdbFPPTEMKKbo8wbzfQa5meQdHOTpmqbHJYQUPHcNhEmOI1YDj4sd
23 | vwGTiaQHbwxNZCWL6Qb+l6PXWVVTdlxU7RKJ2RqaWs7JDCs0U7ggvD0v2Vl7hQrI
24 | 3U692wKBgQC65W0277Kk8sj4Gxc/32mkSfnPMCbvxP0qiMt9pracAVTcHfr4ZQKu
25 | qMcPKyVMMYRM1zCc59aLt2L5OUr+WctgRcnnjBRNxLdgcTDxK+FMyzkP9FaUp28M
26 | kbynDyXAdpGxPQ8t18vzjLUjbYWuAZM9+LcgZ6YSV22OjgcdmsH52g==
27 | -----END RSA PRIVATE KEY-----
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/cp_keys/key.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEA1ECrSVVGxHDjCm+gLdGoTPCTeIgTRvin0cE9M6s/GkD0ta3T
3 | y6DClu8GiBml+PQfQtSya5Ezv8EuUXhFhNCpR+3/vMwUjYLBzH5ybAB/NBRL8MJ1
4 | M7WUzm+WSnl1hdYMolX1xy2cy2Um5saItubMONhhVG+hFAsyy9iCDX+FV8anrOPp
5 | CBuYK1B0BaBSafMDus3SR+xq8T6LgTelwr3srJm6Q6A2AzdBsCkm+WcKW534ClRb
6 | MYfMaJQlBYpmtnQt/k8ctUWX1k/kIAJ7GR5Wh/7555wCcVJbnoc4iNgPs1KyNfmH
7 | v2RiEr2lf0BmxpkzUGnNQNaOVqB1/D1ygsNMAwIDAQABAoIBAQDUMOqMX5Jl5K01
8 | y66I3+avNHtZrkAHXaL4UYVL2FE3f+SklGj+U3L1zXPsMCf7IKL3/wd3/iuL8ibK
9 | D8EALFJvtIFMT4HkjuoL9AWT71M7z2a0BNOCpG9liazoO1DAQeNTjzgsrW7o7/Da
10 | GXSn1UgpNDjpXsfb7+4SWBp8QBYgTok/dx/nZyewZsVtkCsnwrm26Y2k8nhynLm1
11 | nGkQBbRKweQJ5O3PrsrZhRO9OXJ10WK/lYHVqRnu4dam8iP8JHKz5CQN/O7x0HI5
12 | VHHAl0Az4+YZe8wrdNhgtkkOhGxwOtIK5Q3eV8st51YBpWbMiDtQ53ghisWtyNzg
13 | EyphOksxAoGBAO1bTWHsuo6srY4cEJJlJ/C7W237iUM2p9MkeOwcewSXtgY19jAb
14 | IalYzn+yIHLqMyJ1H4cA1sBXBooNvkjVd+7niBbE8du2LyHf4avhNHN2tgKIOjpj
15 | GCsitLEqhyQmUUlYC3z8tQbh99b7fqn2kBDnhdSWPojEx84eXQ71IhMPAoGBAOTs
16 | lQ2iT3cqyore02YOieDwSg7n4flAPPG6cTGGQeOyHpNllTy9U/wyEBrHGGSCkjHI
17 | uDICHtYxyBmL6b0H5IyT4vn1Wxm19ecy8zbuK7Lmwd/iWRfKlGr+YQuez/mHVcCG
18 | YMoQvS6j8WOrQxt2wdOMNatgJeJSz66TaRy2QWfNAoGBAOmTWNJN8MSon15itdgq
19 | 3aQj6/SOfOR866h3ktvfpxu85C62eZ+bg4OwVf4J367WVB3LnovvQmYi/ddrcN8h
20 | 2xVqGV020D+DyFwQgnbvdvtNTg2t24dLryP70k8qZ7UmVAXWM+/6i3bLdmbENUCy
21 | 19Ea1XN/quhSpcFr1e37Q133AoGAD5GLXX8BWoBdf+5BgDpS5CpTTwo0EwhsXKAq
22 | XIzd5EdTzwBkktnpYUhiUf/iR8udd6dH55a/VB/UlPAv+DwWLf1MvWUTSf9W9t8/
23 | LSgrbqJE4x34oyaSy2f7X5fwWu76RPqekH9s7kQWAYo/KRn9eo6Zg8spKGgrWZsK
24 | 1foLHq0CgYBJRjKEY79aNuKCJZw60QPpXodJ65RJufXPz9MgDdoxUOtno8eYPfep
25 | KWWyhJsQXhMJNUMZGvQXRXaaZ3ZZp1e1q18CLh1TqbInC1ODW3L/ZAWCpT9ihcdA
26 | Owj1RL042er59qut/nivipmB5fn1hTbRDLq9rng0fsNU9XlrETbUfg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/docker/op_test/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIEvTCCAqWgAwIBAgIJAMjU19gt2p1PMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
3 | BAMMB29wLXRlc3QwHhcNMTgxMDEyMTM0NTExWhcNMTkxMDEyMTM0NTExWjASMRAw
4 | DgYDVQQDDAdvcC10ZXN0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
5 | 2zDYX4tAjA+9Zo4hZdvAzs7mO+b0Lc7Fj878fv0KTBcl4qifi9nVJ87T41+TSOJw
6 | O+w/J21OoFmPKdygVFYRV6bxeu7TEUTgOlE8hOqFULFnryIt1wYQNMGN5GWF3jcF
7 | eDzWVI+gpnn2EkZHx+ADn+y+zR38CBHyyQbqcIM92wTrttGvEQaDJMCEtP4rP68G
8 | TrC3d7MgMrsESp38SaEm1HylMr5VkQ6e6cILlGiXe5QbHr44eGUmQ63PtfEfJFDT
9 | 7JhllRA+C6POdm9OkUoyfiWSaJTHXAl9bKT1SzTnCZH09bS2RKsYZN7WYOEWlrg0
10 | cK0T4qqkGK6LNDIjkXxwm5tqTy55TGHDdfLBoX/sSGVuq6IcO2NZwz+5KN6AeYgY
11 | KJJrYDcHzbmdbckjYKt6FWc7tD96hmkxVR4zwmZXmUeCeH8UZhwTkA0ZFi3Bs1ZA
12 | rpTIbzvCoFQbuPx1evme9USZzM5LxG6OJGYLpQfmJGkXkUfNHPeiaqb3JdHzXdeU
13 | hbLZLHB+3LIg4GsOLSOFJ75vtOYOETQu0T+Bp+qxFMR76CUzzi9fDZf1B1RyJHRe
14 | JzM1jOLIc8wFCNmJ6o3O+dZmv+E3t52Y5dOBAAb8BwldHeeWy5IjkEx4HhFqjnb8
15 | 2r8X2bELIYnkg887IsxhpM3kah9ClDRGk3rkU0QFmvMCAwEAAaMWMBQwEgYDVR0R
16 | BAswCYIHb3AtdGVzdDANBgkqhkiG9w0BAQsFAAOCAgEALsnFnDrX9vdJb43fwxRz
17 | 8r2qiUPF7Tc/oGKEueMRcykw5k/vtoKqqnC8WVDYsP7Ga6f0KP7bgJxR2dx5IikY
18 | Ajzdd7p/5mKBj507STksNmzESdLGuft3JBdidsYU3G2359uJ2+lHcMgScRWUcX+F
19 | /JKYp336t8RcjWcFSeb/wJrHJIxUOL3rkw619LlW/+T1ZlLxCpV9hBuLmqg+3MbB
20 | 9/k5ixdGpnJAo6g6pCmH5r0der20qumMjnecz0MpUXG60f2ODG00G90jXdIGdPdk
21 | tvp41MMqtKQmWHyQxNVn/Bb0JperKf7ECpZe60k97Pfwn5Ei9jzVnMvsdJSVFHdk
22 | L7/H42u1cbCW+UxJmJkbTpWmlv0DW73ZIFaztddS35uheWXvUWyMuA8yxcc7uyjG
23 | dWvwSNuGX6cm9YOfrAZswd2JCYL0LbII6xxKH1/JxW2ScC6M2zMe7CtAmbuIS3Ca
24 | 4wZZLYZd15MhvwHouvyjWfBBrJM2fRTcURCOag2EsPuzfip3lLDAp3TNW9lbobBl
25 | ZLNPhhd9ErKlnb1PHR/C8FAkOEk5uaF+FYb+yUP/LUjE4ydRqQ5vZEc59CG1mb2R
26 | z1b8xDF54lrm7fQliGSJeuc7qLXibvn8m/dIfnTsQB+446VVXuhHgWgVt8AJKIkP
27 | ngB61uUFVpzUGM6d3Xpqnts=
28 | -----END CERTIFICATE-----
29 |
--------------------------------------------------------------------------------
/docker/rp_test/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIEvTCCAqWgAwIBAgIJAKA0L6TMBrDXMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
3 | BAMMB3JwLXRlc3QwHhcNMTgxMDEyMTM0NDU4WhcNMTkxMDEyMTM0NDU4WjASMRAw
4 | DgYDVQQDDAdycC10ZXN0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
5 | xCeKAs1ccDCfnVPN0xti7LNI41tX0qw7/RnaJyQcyAZ4LQ/zyHZpsTGVdkuXHwEl
6 | ddCIWXxG2tXDmqpBgBblFSMui560h6n8+iklCIX4J5mEigEmb47SVcxnXDqvEOQs
7 | uvLq8gF7nFhPT/pRaDQEfS3L/UWWK+UpLKhInwRhoo6p0a7ce8bUg3RzZR0Lioyw
8 | ADJqCoDzM5A1vhzQIyxZIqHsa14lth27id5W7BupsidSLX9+XpuN/ZFRS7k4P6hP
9 | Apea2FjzorkYKJos6cOebPMKIK8ynKFajoKwwkuX5zx9jp7BTJMBIC3WFapJE/Px
10 | DUEfTELTrggX57iRDZGPZHWthg4MkUcH6upPsA5qbOotCwUBiexLakF2EIw52+IR
11 | Dp7gnOrF5trHMh5An3nJ06OmpQ6Kzr08i9gPOTKJbkD9XN9I/2TztRuPApXG0xua
12 | 3lkaOe4n1Q4DWNzOtFdxjEfxaFKg+5lTAo/bJLHwXq5HFWaGleIcFx6Bnz8UdS0r
13 | flZbcw9jdvUTr3EYJgbN0v7ihagheVe7C5DJTg4C8bQBtc6ODfZtuwN9qYBz8B7F
14 | bullE/bLJXtz+RBlSJqtnRygLp2oD2zQfYBFaRS2ofmTwpRzG6v6k0NrGV8vz1/x
15 | AwPvDAxRxxlEDY+CZIsTjRWTwb6hnnJkY90QrpjV7a8CAwEAAaMWMBQwEgYDVR0R
16 | BAswCYIHcnAtdGVzdDANBgkqhkiG9w0BAQsFAAOCAgEACdjPx50+OkO05Sy8xAxY
17 | TPj293fJHDRZa5xopNWsAQL/Wyq4vyCFUt1liYWzX3xr+YkMhwZikv3ibxzviR0Y
18 | AZh5FMsQQiKBFGxksFOoXot5LKGIn+NyaOhKPfOl9aRZHe6tTDDKP8rH0uv0OyJI
19 | eAREGIGpQkAtXhOwtKn8DvsEa/0z74+nxPZH0gTyhZhk0tZIYPphn8+HlUAngSnq
20 | yjuNxrNqK85xDu9FF35IKpxivlm+X9/igXikpxosddNcbDDXWqZrm8/2hHdTPiaw
21 | t88hpHnFqInXtvQB0IxPOJoG9eVHyAcBIWZwN4BExzVJuQFDpsgTdILjWyx/14mQ
22 | IjSEVdsCIex702S6O2/GGq1HoaKj2ObM4Ix1r4S/F3xWYYWuIHrtmlSZuRFIn7cq
23 | bTXKqvzVGGgA+KYZrd6R4mChc3l/3Ic4PlZ5AQhTEZm8A2VvynLoJwyeG8ArsH0H
24 | VE3SInQYu1FtME/ZQvzSGXcFhl4j05jenhj6vpfnsljVEIPRby8YigOlH+vBDMjd
25 | gvdCKXjkpLAuGyWTOq+Ub5gzvcSX9+FnxQ8SipaL0ej+F64yehVZDjgQ0B7CTBJM
26 | hfxcbJ9fPGWHfvI0RSW8pWqVzGa1umW/N4nl/3/4T6+eFcW97C6k/SabXemtGJkn
27 | y9upB8dfLu8hdNt/WorV4AA=
28 | -----END CERTIFICATE-----
29 |
--------------------------------------------------------------------------------
/src/oic/utils/authn/client_saml.py:
--------------------------------------------------------------------------------
1 | import base64
2 |
3 | from oic.utils.authn.client import CLIENT_AUTHN_METHOD
4 | from oic.utils.authn.client import ClientAuthnMethod
5 |
6 | __author__ = "rolandh"
7 |
8 | SAML2_BEARER_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:saml2-bearer"
9 |
10 | try:
11 | from saml2.saml import assertion_from_string
12 | except ImportError:
13 | pass
14 | else:
15 |
16 | class SAML2AuthnMethod(ClientAuthnMethod):
17 | """Authenticating clients using the SAML2 assertion profile."""
18 |
19 | def construct(self, cis, assertion=None, **kwargs):
20 | """
21 | Create the HTTP request.
22 |
23 | :param cis: The request
24 | :param assertion: A SAML2 Assertion
25 | :param kwargs: Extra arguments
26 | :return: Constructed HTTP arguments, in this case none
27 | """
28 | cis["client_assertion"] = base64.urlsafe_b64encode(assertion)
29 | cis["client_assertion_type"] = SAML2_BEARER_ASSERTION_TYPE
30 |
31 | def verify(self, areq, **kwargs):
32 | xmlstr = base64.urlsafe_b64decode(areq["client_assertion"])
33 | try:
34 | assertion = assertion_from_string(xmlstr)
35 | except Exception:
36 | # FIXME: This should catch specific exceptions thrown by `assertion_from_string`
37 | return False
38 | return self._verify_saml2_assertion(assertion)
39 |
40 | def _verify_saml2_assertion(self, assertion):
41 | subject = assertion.subject
42 | audience = []
43 | for ar in subject.audience_restiction:
44 | for aud in ar.audience:
45 | audience.append(aud)
46 |
47 | CLIENT_AUTHN_METHOD["saml2_bearer"] = SAML2AuthnMethod
48 |
--------------------------------------------------------------------------------
/doc/conf.py:
--------------------------------------------------------------------------------
1 | import alabaster
2 | import os
3 | import sys
4 |
5 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src')))
6 |
7 | extensions = [
8 | 'sphinx.ext.autodoc',
9 | 'sphinx.ext.napoleon',
10 | 'sphinxcontrib.autodoc_pydantic',
11 | ]
12 |
13 | autoclass_content = 'both' # Merge the __init__ docstring into the class docstring.
14 | autodoc_member_order = 'bysource' # Order by source ordering
15 | autodoc_pydantic_model_show_config = True
16 | autodoc_pydantic_settings_show_json = False
17 |
18 | templates_path = ['_templates']
19 |
20 | source_suffix = '.rst'
21 |
22 | master_doc = 'index'
23 |
24 | project = u'pyoidc'
25 |
26 | copyright = u'2014, Roland Hedberg'
27 |
28 | version = '0.1'
29 |
30 | release = '0.1'
31 |
32 | exclude_patterns = ['_build']
33 |
34 | pygments_style = 'sphinx'
35 |
36 | html_theme_path = [alabaster.get_path()]
37 |
38 | html_theme = 'alabaster'
39 |
40 | html_static_path = ['_static']
41 |
42 | htmlhelp_basename = 'pyoidcdoc'
43 |
44 | html_theme_options = {
45 | 'description': '',
46 | 'github_button': False,
47 | 'github_user': 'its-dirg',
48 | 'github_repo': 'saml2testGui',
49 | 'github_banner': False,
50 |
51 | }
52 |
53 | html_sidebars = {
54 | '**': [
55 | 'about.html',
56 | 'navigation.html',
57 | 'searchbox.html',
58 | 'donate.html',
59 | ]
60 | }
61 |
62 | man_pages = [
63 | ('index', 'pyoidc', u'pyoidc Documentation',
64 | [u'Roland Hedberg'], 1)
65 | ]
66 |
67 | latex_elements = {}
68 |
69 | latex_documents = [
70 | ('index', 'pyoidc.tex', u'pyoidc Documentation',
71 | u'Roland Hedberg', 'manual'),
72 | ]
73 |
74 | texinfo_documents = [
75 | ('index', 'pyoidc', u'pyoidc Documentation',
76 | u'Roland Hedberg', 'pyoidc', 'One line description of project.',
77 | 'Miscellaneous'),
78 | ]
79 |
--------------------------------------------------------------------------------
/src/oic/utils/shelve_wrapper.py:
--------------------------------------------------------------------------------
1 | import shelve # nosec
2 |
3 | __author__ = "danielevertsson"
4 |
5 |
6 | class ShelfWrapper(object):
7 | def __init__(self, filename):
8 | self.filename = filename
9 |
10 | def keys(self):
11 | db = self._reopen_database()
12 | return db.keys()
13 |
14 | def __len__(self):
15 | db = self._reopen_database()
16 | return db.__len__()
17 |
18 | def has_key(self, key):
19 | return key in self
20 |
21 | def __contains__(self, key):
22 | db = self._reopen_database()
23 | return db.__contains__(key)
24 |
25 | def get(self, key, default=None):
26 | db = self._reopen_database()
27 | return db.get(key, default)
28 |
29 | def __getitem__(self, key):
30 | db = self._reopen_database()
31 | return db.__getitem__(key)
32 |
33 | def __setitem__(self, key, value):
34 | db = self._reopen_database()
35 | db.__setitem__(key, value)
36 |
37 | def __delitem__(self, key):
38 | db = self._reopen_database()
39 | db.__delitem__(key)
40 |
41 | def _reopen_database(self):
42 | return shelve.open(self.filename, writeback=True) # nosec
43 |
44 |
45 | def open(filename):
46 | """
47 | Open a persistent dictionary for reading and writing.
48 |
49 | The filename parameter is the base filename for the underlying
50 | database. As a side-effect, an extension may be added to the
51 | filename and more than one file may be created. The optional flag
52 | parameter has the same interpretation as the flag parameter of
53 | anydbm.open(). The optional protocol parameter specifies the
54 | version of the pickle protocol (0, 1, or 2).
55 |
56 | See the module's __doc__ string for an overview of the interface.
57 | """
58 | return ShelfWrapper(filename)
59 |
--------------------------------------------------------------------------------
/tests/test_shelve_wrapper.py:
--------------------------------------------------------------------------------
1 | # pylint: disable=missing-docstring,no-self-use,redefined-outer-name
2 | import os
3 |
4 | import pytest
5 |
6 | from oic.utils import shelve_wrapper
7 |
8 | __author__ = "mathiashedstrom"
9 |
10 | VALUES = {"key_1": "val_1", "key_2": "val_2", "key_3": "val_3"}
11 |
12 |
13 | def _eq(l1, l2):
14 | return set(l1) == set(l2)
15 |
16 |
17 | @pytest.fixture
18 | def db(tmpdir):
19 | return shelve_wrapper.open(os.path.join(tmpdir.strpath, "test_db_shelve_wrapper"))
20 |
21 |
22 | @pytest.fixture
23 | def populated_db(db):
24 | for k, v in VALUES.items():
25 | db[k] = v
26 |
27 | return db
28 |
29 |
30 | class TestShelfWrapper(object):
31 | def test_keys(self, populated_db):
32 | assert _eq(populated_db.keys(), VALUES.keys())
33 |
34 | def test_contains(self, populated_db):
35 | for k in VALUES.keys():
36 | assert k in populated_db
37 |
38 | assert "NO_KEY" not in populated_db
39 |
40 | def test_get(self, populated_db):
41 | for k, v in VALUES.items():
42 | assert populated_db.get(k) == v
43 |
44 | assert populated_db.get("NO_KEY") is None
45 |
46 | def test_getitem(self, populated_db):
47 | for k, v in VALUES.items():
48 | assert populated_db[k] == v
49 |
50 | with pytest.raises(KeyError):
51 | populated_db["NO_KEY"] # pylint: disable=pointless-statement
52 |
53 | def test_delitem(self, populated_db):
54 | key = list(VALUES.keys())[0]
55 | del populated_db[key]
56 |
57 | with pytest.raises(KeyError):
58 | populated_db[key] # pylint: disable=pointless-statement
59 |
60 | def test_len(self, db):
61 | assert len(db) == 0
62 |
63 | length = 4
64 | for i in range(length):
65 | db["key_{}".format(i)] = "foo"
66 | assert len(db) == length
67 |
--------------------------------------------------------------------------------
/oidc_example/op2/htdocs/op_session_iframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Check session iframe
6 |
7 |
8 |
9 |
10 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/oidc_example/op3/htdocs/op_session_iframe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Check session iframe
6 |
7 |
8 |
9 |
10 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/oic/utils/template_render.py:
--------------------------------------------------------------------------------
1 | """Implementation of basic templating engine."""
2 |
3 | FORM_POST = """
4 |
5 | Submit This Form
6 |
7 |
8 |
11 |
12 | """
13 |
14 |
15 | VERIFY_LOGOUT = """
16 |
17 | Please verify logout
18 |
19 |
20 |