[ New addition ] Source code corresponding to this article ( Multiple flow, clients, call python api): 
https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks
<https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks>

Currently in use asp.net core 2.0 ( Mainly web api) Make a project , Some functions need to be used js Client call python Of pandas,
So we need to build a python Of rest api, I chose it for the time being hug, The official website is here :http://www.hug.rest/
<http://www.hug.rest/>.

The current project uses identity server 4, Some more web api and js client.

Early background source code of the project : https://github.com/solenovex/asp.net-core-2.0-web-api-boilerplate
<https://github.com/solenovex/asp.net-core-2.0-web-api-boilerplate>

Start configuration below identity server 4, I use windows.

add to ApiResource:

stay authorization server Add red section to profile in project , This part is python hug Of api:
public static IEnumerable<ApiResource> GetApiResources() { return new
List<ApiResource> { new ApiResource(SalesApiSettings.ApiName,
SalesApiSettings.ApiDisplayName) { UserClaims= { JwtClaimTypes.Name,
JwtClaimTypes.PreferredUserName, JwtClaimTypes.Email } },new ApiResource("
purchaseapi", " Procurement and raw material warehouse API") { UserClaims = { JwtClaimTypes.Name,
JwtClaimTypes.PreferredUserName, JwtClaimTypes.Email } },new
ApiResource("hugapi", "Hug API") { UserClaims = { JwtClaimTypes.Name,
JwtClaimTypes.PreferredUserName, JwtClaimTypes.Email } } }; }
modify js Client Configuration of :
// Sales JavaScript Client new Client { ClientId = SalesApiSettings.ClientId,
ClientName= SalesApiSettings.ClientName, AllowedGrantTypes =
GrantTypes.Implicit, AllowAccessTokensViaBrowser= true, AccessTokenLifetime = 60
*10, AllowOfflineAccess = true, RedirectUris = { $"{Startup.Configuration["
MLH:SalesApi:ClientBase"]}/login-callback", $"{Startup.Configuration["
MLH:SalesApi:ClientBase"]}/silent-renew.html" }, PostLogoutRedirectUris = {
Startup.Configuration["MLH:SalesApi:ClientBase"] }, AllowedCorsOrigins = {
Startup.Configuration["MLH:SalesApi:ClientBase"] },
AlwaysIncludeUserClaimsInIdToken= true, AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email, SalesApiSettings.ApiName,"hugapi"
} }
modify js Client's oidc client configuration option :

add to hugapi, And authorization server Configuration correspondence .
{ authority: 'http://localhost:5000', client_id: 'sales', redirect_uri:
'http://localhost:4200/login-callback', response_type: 'id_token token', scope:
'openid profile salesapihugapi email', post_logout_redirect_uri:
'http://localhost:4200', silent_redirect_uri:
'http://localhost:4200/silent-renew.html', automaticSilentRenew: true,
accessTokenExpiringNotificationTime:4, // silentRequestTimeout:10000, userStore:
new WebStorageStateStore({ store: window.localStorage }) }
establish Python Hug api

( Optional ) install virtualenv:
pip install virtualenv
And then create a directory somewhere :
mkdir hugapi && cd hugapi
Build a virtual environment :
virtualenv venv
Activate virtual environment :
venv\Scripts\activate
And then it's about like this :



install hug:
pip install hug
At this time , For reference hug Documents for . Then build a simple api. create file main.py:
import hug @hug.get('/home') def root(): return 'Welcome home!'
function :
hug -f main.py
The result is easy to use :



And then you need to install these :
pip install cryptography pyjwt hug_middleware_cors
among pyjwt It's a yes encode and decode JWT Library of , If using RS256 Algorithmic words , Installation is also required cryptography. 

and hug_middleware_cors yes hug A cross domain access middleware based on ( because js Client and this api Not under the same domain name ).

Add required references :
import hug import jwt import json import urllib.request from jwt.algorithms
import get_default_algorithms from hug_middleware_cors import CORSMiddleware
And the right thing to do is to go through Authorization Server Of discovery endpoint To find out jwks_uri,

identity server 4 Of discovery endpoint The address of is :

http://localhost:5000/.well-known/openid-configuration
<http://localhost:5000/.well-known/openid-configuration>, It can find all kinds of nodes and information :



 

But I'll just write it down jwks_uri bar :
response = urllib.request.urlopen('
http://localhost:5000/.well-known/openid-configuration/jwks') still_json =
json.dumps(json.loads(response.read())['keys'][0])
identity server 4 Of jwks_uri, Inside is public key, It's structured like this :



And I use jwt library , Parameters of can only be passed to the json, It could be keys[0].

So the last line of code above looks a little bit .......

If using python-jose This library will be simpler , But in me windows Always fail to install on your computer , So it's a good idea pyjwt bar .

Then let's hug api use cors middleware :
api = hug.API(__name__) api.http.add_middleware(CORSMiddleware(api))
And then there was hug Of authentication part :
def token_verify(token): token = token.replace('Bearer ', '') rsa =
get_default_algorithms()['RS256'] cert = rsa.from_jwk(still_json) try: result =
jwt.decode(token, cert, algorithms=['RS256'], audience='hugapi') print(result)
return result except jwt.DecodeError: return False token_key_authentication =
hug.authentication.token(token_verify)
adopt rsa.from_jwk(json) You'll get it key (certificate),
And then through jwt.decode Methods token Verify and decode, The algorithm is RS256, This method requires that if token It contains aud,
Then the method needs to be specified audience, that is hugapi.

Last modification api method , Plus verification :
@hug.get('/home', requires=token_key_authentication) def root(): return '
Welcome home!'
Last run hug api:
hug -f main.py
Port should be 8000.

function js client , land , And call this hug api http://localhost:8000/home:

( my js Client is angular5 Of , This is not open source , Company property , But configuration oidc-client It's still very simple , use )



return 200, The content is : 



to glance at hug Of log:



token Verified and parsed correctly . So you can enter root Method .

 
other python api frame , It's the same thing .

[ New addition ]  Source code corresponding to this article ( Multiple flow, clients, call python api): 
https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks
<https://github.com/solenovex/Identity-Server-4-Python-Hug-Api-Jwks>

You can use this example to build your own
https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/7_JavaScriptClient 

<https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/7_JavaScriptClient>

There's another official nodejs api Example of : https://github.com/lyphtec/idsvr4-node-jwks
<https://github.com/lyphtec/idsvr4-node-jwks>

Today's revised code : 
import json import hug import jwt import requests from jwt.algorithms import
get_default_algorithmsfrom hug_middleware_cors import CORSMiddleware api =
hug.API(__name__) api.http.add_middleware(CORSMiddleware(api)) def
token_verify(token): access_token= token.replace('Bearer ', '') token_header =
jwt.get_unverified_header(access_token) res= requests.get( '
http://localhost:5000/.well-known/openid-configuration') jwk_uri = res.json()['
jwks_uri'] res = requests.get(jwk_uri) jwk_keys = res.json() rsa =
get_default_algorithms()['RS256'] key = json.dumps(jwk_keys['keys'][0])
public_key= rsa.from_jwk(key) try: result = jwt.decode(access_token,
public_key, algorithms=[ token_header['alg']], audience='api1') return result
except jwt.DecodeError: return False token_key_authentication =
hug.authentication.token(token_verify) @hug.get('/identity', requires=
token_key_authentication)def root(user: hug.directives.user): print(user) return
user
  My blog will be moved to Tencent cloud soon + community , Invite everyone to settle in together :https://cloud.tencent.com/developer/support-plan