commit
f98b117a0e
|
@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
### [Unreleased]
|
||||
|
||||
##### Added
|
||||
- Polish translations.
|
||||
- Examples section in documentation.
|
||||
|
||||
##### Fixed
|
||||
- CORS in discovery and userinfo endpoint.
|
||||
- Client type public bug when created using the admin.
|
||||
|
||||
### [0.3.7] - 2016-08-31
|
||||
|
||||
##### Added
|
||||
|
|
|
@ -31,6 +31,7 @@ Contents:
|
|||
sections/userconsent
|
||||
sections/oauth2
|
||||
sections/settings
|
||||
sections/examples
|
||||
sections/contribute
|
||||
..
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ Improve Documentation
|
|||
|
||||
We use `Sphinx <http://www.sphinx-doc.org/>`_ for generate this documentation. I you want to add or modify something just:
|
||||
|
||||
* Install Sphinx ``pip install sphinx`` and this theme ``pip install sphinx-rtd-theme``.
|
||||
* Install Sphinx (``pip install sphinx``) and the auto-build tool (``pip install sphinx-autobuild``).
|
||||
* Move inside the docs folder. ``cd docs/``
|
||||
* Generate the HTML. ``make html``
|
||||
* Open ``docs/_build/html/index.html`` on a browser.
|
||||
* Generate and watch docs by running ``sphinx-autobuild . _build/``.
|
||||
* Open ``http://127.0.0.1:8000`` on a browser.
|
||||
|
|
94
docs/sections/examples.rst
Normal file
94
docs/sections/examples.rst
Normal file
|
@ -0,0 +1,94 @@
|
|||
.. _examples:
|
||||
|
||||
Examples
|
||||
########
|
||||
|
||||
Pure JS client using Implicit Flow
|
||||
==================================
|
||||
|
||||
Testing OpenID Connect flow can be as simple as putting one file with a few functions on the client and calling the provider. Let me show.
|
||||
|
||||
**01. Setup the provider**
|
||||
|
||||
You can use the example project code to run your OIDC Provider at ``localhost:8000``.
|
||||
|
||||
Go to the admin site and create a public client with a response_type ``id_token token`` and a redirect_uri ``http://localhost:3000``.
|
||||
|
||||
.. note::
|
||||
Remember to create at least one **RSA Key** for the server. ``python manage.py creatersakey``
|
||||
|
||||
**02. Create the client**
|
||||
|
||||
As relying party we are going to use a JS library created by Nat Sakimura. `Here is the article <https://nat.sakimura.org/2014/12/10/making-a-javascript-openid-connect-client/>`_.
|
||||
|
||||
**index.html**::
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<title>OIDC RP</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<center>
|
||||
<h1>OpenID Connect RP Example</h1>
|
||||
<button id="login-button">Login</button>
|
||||
</center>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
|
||||
<script src="https://www.sakimura.org/test/openidconnect.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var clientInfo = {
|
||||
client_id : '',
|
||||
redirect_uri : 'http://localhost:3000'
|
||||
};
|
||||
|
||||
OIDC.setClientInfo(clientInfo);
|
||||
|
||||
var providerInfo = OIDC.discover('http://localhost:8000');
|
||||
|
||||
OIDC.setProviderInfo(providerInfo);
|
||||
OIDC.storeInfo(providerInfo, clientInfo);
|
||||
|
||||
// Restore configuration information.
|
||||
OIDC.restoreInfo();
|
||||
|
||||
// Get Access Token
|
||||
var token = OIDC.getAccessToken();
|
||||
|
||||
// Make userinfo request using access_token.
|
||||
if (token !== null) {
|
||||
$.get('http://localhost:8000/userinfo/?access_token='+token, function( data ) {
|
||||
alert('USERINFO: '+ JSON.stringify(data));
|
||||
});
|
||||
}
|
||||
|
||||
// Make an authorization request if the user click the login button.
|
||||
$('#login-button').click(function (event) {
|
||||
OIDC.login({
|
||||
scope : 'openid profile email',
|
||||
response_type : 'id_token token'
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
.. note::
|
||||
Remember that you must set your client_id (line 21).
|
||||
|
||||
**03. Make an authorization request**
|
||||
|
||||
By clicking the login button an authorization request has been made to the provider. After you accept it, the provider will redirect back to your previously registered ``redirect_uri`` with all the tokens requested.
|
||||
|
||||
**04. Requesting user information**
|
||||
|
||||
Now having the access_token in your hands you can request the user information by making a request to the ``/userinfo`` endpoint of the provider.
|
||||
|
||||
In this example we display information in the alert box.
|
|
@ -1,6 +1,6 @@
|
|||
# Example Project
|
||||
|
||||
![Example Project](http://i.imgur.com/IK3OZjx.png)
|
||||
![Example Project](https://s17.postimg.org/4jjj8lavj/Screen_Shot_2016_09_07_at_15_58_43.png)
|
||||
|
||||
Run your own OIDC provider in a second. This is a Django app with all the necessary things to work with `django-oidc-provider` package.
|
||||
|
||||
|
@ -31,6 +31,7 @@ Run your provider.
|
|||
```bash
|
||||
$ python manage.py migrate
|
||||
$ python manage.py creatersakey
|
||||
$ python manage.py createsuperuser
|
||||
$ python manage.py runserver
|
||||
```
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "provider_app.settings")
|
||||
if __name__ == '__main__':
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'provider_app',
|
||||
'myapp',
|
||||
'oidc_provider',
|
||||
]
|
||||
|
||||
|
@ -50,9 +50,9 @@ TEMPLATES = [
|
|||
},
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'provider_app.urls'
|
||||
ROOT_URLCONF = 'myapp.urls'
|
||||
|
||||
WSGI_APPLICATION = 'provider_app.wsgi.application'
|
||||
WSGI_APPLICATION = 'myapp.wsgi.application'
|
||||
|
||||
# Database
|
||||
|
46
example_project/myapp/templates/base.html
Normal file
46
example_project/myapp/templates/base.html
Normal file
|
@ -0,0 +1,46 @@
|
|||
{% load i18n staticfiles %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<title>{% trans 'OpenID Provider Example' %}</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.2/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/custom.css' %}">
|
||||
|
||||
</head>
|
||||
|
||||
<nav class="navbar navbar-fixed-top navbar-light bg-faded">
|
||||
<div class="container">
|
||||
<a class="navbar-brand m-b-0" href="{% url 'home' %}">{% trans 'OpenID Provider Example' %}</a>
|
||||
<form class="form-inline pull-xs-right">
|
||||
<ul class="nav navbar-nav">
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_superuser %}
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'admin:index' %}"><i class="fa fa-external-link" aria-hidden="true"></i> {% trans 'Admin' %}</a></li>
|
||||
{% endif %}
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'logout' %}"><i class="fa fa-times" aria-hidden="true"></i> {% trans 'Logout' %}</a></li>
|
||||
{% else %}
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'login' %}"><i class="fa fa-sign-in" aria-hidden="true"></i> {% trans 'Login' %}</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="https://github.com/juanifioren/django-oidc-provider" target="_blank"><i class="fa fa-github-alt"></i> {% trans 'View on Github' %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.2/js/bootstrap.min.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
14
example_project/myapp/templates/home.html
Normal file
14
example_project/myapp/templates/home.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<section class="text-xs-center">
|
||||
<div class="container">
|
||||
<h1 class="jumbotron-heading">{% trans 'Welcome' %}{% if user.is_authenticated %} {{ user.username }}{% endif %}!</h1>
|
||||
<p class="lead text-muted">{% trans 'This is an example of an OpenID Connect 1.0 Provider. Built with the <a href="https://www.djangoproject.com/" target="_BLANK"><u>Django Framework</u></a> and <a href="https://github.com/juanifioren/django-oidc-provider" target="_BLANK"><u>django-oidc-provider</u></a> package.' %}</p>
|
||||
<p><a href="{% url 'admin:index' %}oidc_provider/client/" class="btn btn-primary btn-lg">{% trans 'Create your clients' %}</a></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
29
example_project/myapp/templates/login.html
Normal file
29
example_project/myapp/templates/login.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<form method="post" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{% trans 'Your username and password didn\'t match. Please try again.' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<fieldset class="form-group">
|
||||
<input class="form-control form-control-lg" type="text" name="username" placeholder="{% trans 'Username' %}">
|
||||
</fieldset>
|
||||
<fieldset class="form-group">
|
||||
<input class="form-control form-control-lg" type="password" name="password" placeholder="{% trans 'Password' %}">
|
||||
</fieldset>
|
||||
<fieldset class="form-group">
|
||||
<input class="btn btn-primary btn-lg btn-block" type="submit" value="{% trans 'Enter' %}" />
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
25
example_project/myapp/templates/oidc_provider/authorize.html
Normal file
25
example_project/myapp/templates/oidc_provider/authorize.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h2>{% trans 'Request for Permission' %}</h2>
|
||||
<p class="lead">Client <i>{{ client.name }}</i> would like to access this information of you.</p>
|
||||
<form method="post" action="{% url 'oidc_provider:authorize' %}">
|
||||
{% csrf_token %}
|
||||
{{ hidden_inputs }}
|
||||
<ul>
|
||||
{% for scope in scopes %}
|
||||
<li><strong>{{ scope.name }}</strong> <br><i class="text-muted">{{ scope.description }}</i></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<br>
|
||||
<input type="submit" class="btn btn-primary btn-block btn-lg" name="allow" value="{% trans 'Accept' %}" />
|
||||
<input type="submit" class="btn btn-secondary btn-block" value="{% trans 'Decline' %}" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
12
example_project/myapp/templates/oidc_provider/error.html
Normal file
12
example_project/myapp/templates/oidc_provider/error.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h2>{{ error }}</h2>
|
||||
<p class="lead">{{ description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "provider_app.settings")
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
|
@ -1,15 +0,0 @@
|
|||
body {
|
||||
background-color: #536dfe;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
flex: 1 0 auto;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding-top: 0px !important;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
|
||||
<title>OpenID Provider Example</title>
|
||||
|
||||
<link rel="stylesheet" href="http://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'css/custom.css' %}">
|
||||
|
||||
</head>
|
||||
|
||||
<div class="navbar-fixed">
|
||||
<nav class="white">
|
||||
<div class="nav-wrapper">
|
||||
<a href="{% url 'home' %}" class="brand-logo center black-text">OpenID Provider</a>
|
||||
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_superuser %}
|
||||
<li><a href="{% url 'admin:index' %}" class="black-text">{% trans 'Admin' %}</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{% url 'logout' %}" class="black-text">X</a></li>
|
||||
{% else %}
|
||||
<li><a href="{% url 'login' %}" class="black-text"><i class="material-icons left">input</i> {% trans 'Login' %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="main-container" class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<footer class="page-footer white">
|
||||
<div class="footer-copyright">
|
||||
<div class="container black-text"><a href="https://www.linkedin.com/in/juanifioren" target="_BLANK">Created by Juan Ignacio Fiorentino</a><a class="right" href="https://github.com/juanifioren/django-oidc-provider" target="_BLANK">View on Github</a></div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/js/materialize.min.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,28 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12 m10 offset-m1">
|
||||
<div class="card hoverable">
|
||||
<div class="card-content">
|
||||
<h1 class="center-align flow-text indigo-text text-lighten-1">Example of an OpenID Connect 1.0 Provider. Built with the <a href="https://www.djangoproject.com/" target="_BLANK"><u>Django Framework</u></a> and <a href="https://github.com/juanifioren/django-oidc-provider" target="_BLANK"><u>django-oidc-provider</u></a> package.</h1>
|
||||
<p class="flow-text">Start by creating your clients <a href="{% url 'admin:index' %}oidc_provider/client/">here</a>.</p>
|
||||
<p class="flow-text">Also check that you've created at least one server key, do it <a href="{% url 'admin:index' %}oidc_provider/rsakey/">here</a>.</p>
|
||||
<div class="collection with-header">
|
||||
<div class="collection-header"><h4>Server Endpoints</h4></div>
|
||||
<a href="{% url 'oidc_provider:provider_info' %}" class="collection-item indigo-text text-lighten-1">{% url 'oidc_provider:provider_info' %}</a>
|
||||
<a href="{% url 'oidc_provider:jwks' %}" class="collection-item indigo-text text-lighten-1">{% url 'oidc_provider:jwks' %}</a>
|
||||
<a href="{% url 'oidc_provider:authorize' %}" class="collection-item indigo-text text-lighten-1">{% url 'oidc_provider:authorize' %}</a>
|
||||
<a href="{% url 'oidc_provider:token' %}" class="collection-item indigo-text text-lighten-1">{% url 'oidc_provider:token' %}</a>
|
||||
<a href="{% url 'oidc_provider:userinfo' %}" class="collection-item indigo-text text-lighten-1">{% url 'oidc_provider:userinfo' %}</a>
|
||||
<a href="{% url 'oidc_provider:logout' %}" class="collection-item indigo-text text-lighten-1">{% url 'oidc_provider:logout' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,40 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12 m8 offset-m2 l6 offset-l3">
|
||||
<div class="card hoverable">
|
||||
<div class="card-content">
|
||||
<div class="row">
|
||||
{% if form.errors %}
|
||||
<h5 class="red-text text-darken-1 flow-text center-align">Your username and password didn't match. Please try again.</h5>
|
||||
{% endif %}
|
||||
<form class="col s12" method="post" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<i class="material-icons prefix">account_circle</i>
|
||||
<input id="username" name="username" type="text" class="validate">
|
||||
<label for="username">{% trans 'Username' %}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<i class="material-icons prefix">lock</i>
|
||||
<input id="password" name="password" type="password" class="validate">
|
||||
<label for="password">{% trans 'Password' %}</label>
|
||||
</div>
|
||||
</div>
|
||||
<input class="waves-effect waves-light btn-large right green" type="submit" value="{% trans 'Enter' %}" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,27 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12 m8 offset-m2 l6 offset-l3">
|
||||
<h4 class="grey-text text-lighten-3">Request for Permission</h4>
|
||||
<div class="card hoverable">
|
||||
<div class="card-content">
|
||||
<p class="flow-text">Client <i>{{ client.name }}</i> would like to access this information of you.</p>
|
||||
<form method="post" action="{% url 'oidc_provider:authorize' %}">
|
||||
{% csrf_token %}
|
||||
{{ hidden_inputs }}
|
||||
<ul class="collection">
|
||||
{% for scope in params.scope %}
|
||||
<li class="collection-item">{{ scope | capfirst }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<input class="waves-effect waves-light btn grey" type="submit" value="Cancel" />
|
||||
<input name="allow" class="waves-effect waves-light btn green right" type="submit" value="Authorize" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -1,16 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12 m8 offset-m2 l6 offset-l3">
|
||||
<div class="card hoverable">
|
||||
<div class="card-content">
|
||||
<h4 class="center-align red-text text-lighten-1">{{ error }}</h4>
|
||||
<p>{{ description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -39,7 +39,7 @@ class ClientForm(ModelForm):
|
|||
elif (self.cleaned_data['client_type'] == 'confidential') and instance.client_secret:
|
||||
secret = instance.client_secret
|
||||
else:
|
||||
if (instance.client_type == 'confidential'):
|
||||
if (self.cleaned_data['client_type'] == 'confidential'):
|
||||
secret = md5(uuid4().hex.encode()).hexdigest()
|
||||
|
||||
return secret
|
||||
|
|
|
@ -171,6 +171,7 @@ def userinfo(request, *args, **kwargs):
|
|||
dic.update(extra_claims.create_response_dic())
|
||||
|
||||
response = JsonResponse(dic, status=200)
|
||||
response['Access-Control-Allow-Origin'] = '*'
|
||||
response['Cache-Control'] = 'no-store'
|
||||
response['Pragma'] = 'no-cache'
|
||||
|
||||
|
@ -203,7 +204,10 @@ class ProviderInfoView(View):
|
|||
dic['token_endpoint_auth_methods_supported'] = ['client_secret_post',
|
||||
'client_secret_basic']
|
||||
|
||||
return JsonResponse(dic)
|
||||
response = JsonResponse(dic)
|
||||
response['Access-Control-Allow-Origin'] = '*'
|
||||
|
||||
return response
|
||||
|
||||
|
||||
class JwksView(View):
|
||||
|
|
Loading…
Reference in a new issue