- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用从 Microsoft 到客户端的 jwt token 来验证从它到 Web API(服务器)的请求。我可以控制客户端 (js) 和服务器 (Python) 的代码。
在客户端,我使用以下请求获取 token (用户通过租户上的密码/2FA 声明):
`https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/authorize
?response_type=id_token+token
&client_id=${CLIENT_ID}
&redirect_uri=${redirect_uri}
&scope=openid+email+profile
&state=${guid()}
&nonce=${guid()}`
这里的guid
是一个唯一值,TENANT_ID
是租户,CLIENT_ID
是客户端。
获得此 token 后,我将其作为授权 header 发送,如下所示:
init = {
headers: {
'Authorization': `Bearer ${token}`,
}
}
return fetch(url, init).then(response => {
return response.json()
})
然后在服务器上,我检索 token 并验证它:
if 'Authorization' in request.headers and request.headers['Authorization'].startswith('Bearer '):
token = request.headers['Authorization'][len('Bearer '):]
from authlib.jose import jwt
claims = jwt.decode(token, jwk)
其中 jwk
是 https://login.microsoftonline.com/{TENANT_ID}/discovery/v2.0/keys
的内容。
整个流程一直有效,直到验证失败,并出现以下错误:
authlib.jose.errors.InvalidHeaderParameterName: invalid_header_parameter_name: Invalid Header Parameter Names: nonce
这表明 token 的 header 包含一个 key nonce
(我验证了它)。
查看 Microsoft 关于此的文档,here , header 上没有对 nonce
的引用 - 仅在有效负载上。
Q1:我做错了什么?
问题 2:假设 Microsoft 将 nonce 放在错误的位置( header 而不是负载),是否可以在将 nonce 传递给 jose 的身份验证库之前从 header (在服务器端)删除 nonce ?这样做安全吗?
最佳答案
参见:https://robertoprevato.github.io/Validating-JWT-Bearer-tokens-from-Azure-AD-in-Python/
以下是我在我的 API 中验证 Azure AD Id_tokens 的方法:
import base64
import jwt
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
def ensure_bytes(key):
if isinstance(key, str):
key = key.encode('utf-8')
return key
def decode_value(val):
decoded = base64.urlsafe_b64decode(ensure_bytes(val) + b'==')
return int.from_bytes(decoded, 'big')
def rsa_pem_from_jwk(jwk):
return RSAPublicNumbers(
n=decode_value(jwk['n']),
e=decode_value(jwk['e'])
).public_key(default_backend()).public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# obtain jwks as you wish: configuration file, HTTP GET request to the endpoint returning them;
jwks = {
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "piVlloQDSMKx...",
"x5t": "piVlloQDSMKx...",
"n": "0XhhwpmEpN-jDBapnzhF...",
"e": "AQAB",
"x5c": [
"MIIDBTCCAe2gAwIBAgIQMCJcg...."
],
"issuer": "https://login.microsoftonline.com/{tenant}/v2.0"
}
]
}
# configuration, these can be seen in valid JWTs from Azure B2C:
valid_audiences = ['dd050a67-ebfd-xxx-xxxx-xxxxxxxx'] # id of the application prepared previously
class InvalidAuthorizationToken(Exception):
def __init__(self, details):
super().__init__('Invalid authorization token: ' + details)
def get_kid(token):
headers = jwt.get_unverified_header(token)
if not headers:
raise InvalidAuthorizationToken('missing headers')
try:
return headers['kid']
except KeyError:
raise InvalidAuthorizationToken('missing kid')
def get_jwk(kid):
for jwk in jwks.get('keys'):
if jwk.get('kid') == kid:
return jwk
raise InvalidAuthorizationToken('kid not recognized')
def get_issuer(kid):
for jwk in jwks.get('keys'):
if jwk.get('kid') == kid:
return jwk.get('issuer')
raise InvalidAuthorizationToken('kid not recognized')
def get_public_key(token):
return rsa_pem_from_jwk(get_jwk(get_kid(token)))
def validate_jwt(jwt_to_validate):
try:
public_key = get_public_key(jwt_to_validate)
issuer = get_issuer(kid)
options = {
'verify_signature': True,
'verify_exp': True, # Skipping expiration date check
'verify_nbf': False,
'verify_iat': False,
'verify_aud': True # Skipping audience check
}
decoded = jwt.decode(jwt_to_validate,
public_key,
options=options,
algorithms=['RS256'],
audience=valid_audiences,
issuer=issuer)
# do what you wish with decoded token:
# if we get here, the JWT is validated
print(decoded)
except Exception as ex:
print('The JWT is not valid!')
return False
else:
return decoded
print('The JWT is valid!')
关于jwt - 如何验证 Microsoft jwt id_token?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59151559/
我正在尝试创建一个 Shiny 的应用程序,该应用程序首先使用 OAuth 进行授权(请参阅 https://developers.google.com/identity/sign-in/web/si
我成功地将我的 Alexa 应用程序(客户端)链接到我们公司的 OpenID Connect 平台(授权服务器)。 我们的授权服务器向 Alexa 客户端返回以下信息: { "access_toke
我已经在java中成功实现了OpenID Connect。仅剩余部分经过验证 id_token。我已经使用 base64 解码了 id_token 并获取了用户电子邮件和姓名。现在我想验证 id_to
我正在实现“使用 PayPal 登录”功能。应该相当简单,但不幸的是 PayPal 缺少文档(只描述了一些基本的东西)。 我使用“使用 PayPal 登录”小部件获取 authorization_co
我想注册一个守护程序应用程序并为其授予 Microsoft graph API 的应用程序权限。现在,我将从我的客户端将 client_id 和 key 传递到端点,然后进行如下调用app.acqui
我想注册一个守护程序应用程序并为其授予 Microsoft graph API 的应用程序权限。现在,我将从我的客户端将 client_id 和 key 传递到端点,然后进行如下调用app.acqui
使用 Google OAuth2 API 时,我收到不一致的回复参数。 范围:['电子邮件','个人资料'] 预期响应: { access_token: 'ya29.fQB...aYSwXTK7E
使用 response_type=code 对支持 OpenID 的 OAuth2 授权服务器进行身份验证后与 scope=openid email ,调用 token 端点应返回 id_token
var login = function () { var deferred = $q.defer(); gapi.auth.authorize({
我正在使用 IdentityServer4,我想将计算字段添加到 access_token/id_token。 此类字段的示例可以是用户的 IP(或 token 绑定(bind)哈希), token
我们正在开发一个 Multi-Tenancy Web 应用程序。我们的租户将使用 Windows Azure Active Directory 进行身份验证。我们正在使用 OWIN OpenIdCon
我关注了以下博客 post实现苹果登录。它是很久以前写的,当时没有带有用户信息的 id_token。当我请求 token API 时,我收到包含多个字段的 JSON。问题是如何解码 id_token
引用 JWT(id_token) decoding docs 后 我很困惑主要服务提供商是否会遵循相同的技术...... 微软oauth2.0客户端在git project getUserEmailF
我在 Azure AD 中注册了一个应用程序。 如果我在 Web API 级别和客户端(SPA 应用程序)级别使用相同的应用程序 ID,为什么两个 Azure AD 身份验证库都这样做 (ADAL J
我正在使用从 Microsoft 到客户端的 jwt token 来验证从它到 Web API(服务器)的请求。我可以控制客户端 (js) 和服务器 (Python) 的代码。 在客户端,我使用以下请
我已成功通过我的 Angular 应用程序中的 Azure AD ( https://login.microsoftonline.com/ {tenantId}/oauth2/v2.0/authori
引用 JWT(id_token) decoding docs 后 我很困惑主要服务提供商是否会遵循相同的技术...... 微软oauth2.0客户端在git project getUserEmailF
我在 Azure AD 中注册了一个应用程序。 如果我在 Web API 级别和客户端(SPA 应用程序)级别使用相同的应用程序 ID,为什么两个 Azure AD 身份验证库都这样做 (ADAL J
我正在使用从 Microsoft 到客户端的 jwt token 来验证从它到 Web API(服务器)的请求。我可以控制客户端 (js) 和服务器 (Python) 的代码。 在客户端,我使用以下请
我目前正在实现 Google OpenID 以在我的网站上实现使用 google 登录。继tutorial given by google 。它强调只有 id_token 是发送到后端服务器的东西。由
我是一名优秀的程序员,十分优秀!