验证 Azure 广告访问令牌时签名无效,但 ID 令牌有效
Invalid signature while validating Azure ad access token, but id token works
我在使用 jwt.io 验证我的 Azure 广告访问令牌时收到无效签名。然而,我的 id 令牌验证得很好!
我已经看到并尝试了
中建议的解决方案
和
https://nicksnettravels.builttoroam.com/post/2017/01/24/Verifying-Azure-Active-Directory-JWT-Tokens.aspx
但都不适用于我的访问令牌。
访问和 Id 令牌是通过 Adal.js:
生成的
var endpoints = {
"https://graph.windows.net": "https://graph.windows.net"
};
var configOptions = {
tenant: "<ad>.onmicrosoft.com", // Optional by default, it sends common
clientId: "<app ID from azure portal>",
postLogoutRedirectUri: window.location.origin,
endpoints: endpoints,
}
window.authContext = new AuthenticationContext(configOptions);
为什么我可以验证我的 ID 令牌,而不是我的访问令牌?
请参考话题:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609
but if look at the Jwt.Header you will see a 'nonce'. This means you need special processing. Normal processing will fail.
因此,如果随机数包含在访问令牌中,使用 JWT.io 或 JwtSecurityToken 验证签名将不会成功。
如果其他人有无效签名错误,您应该查看此评论:https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/521#issuecomment-577400515
解决了我的配置问题。
本质上,如果您正在获取访问令牌来访问您自己的资源服务器而不是 Graph API,您的范围参数应该是 [CLIENT_ID]/.default
(如果您使用访问令牌来访问图 API,您不需要自己验证令牌)
感谢@Antoine,我修复了我的代码。在这里,我将让我个人的 vue.js 插件可供其他人参考:
import { PublicClientApplication } from '@azure/msal-browser'
import { Notify } from 'quasar'
export class MsalService {
_msal = null
_store = null
_loginRequest = null
constructor (appConfig, store) {
this._store = store
this._msal = new PublicClientApplication(
{
auth: {
clientId: appConfig.auth.clientId,
authority: appConfig.auth.authority
},
cache: {
cacheLocation: 'localStorage'
}
})
this._loginRequest = {
scopes: [`${appConfig.auth.clientId}/.default`]
}
}
async handleResponse (response) {
await this._store.dispatch('auth/setResponse', response)
const accounts = this._msal.getAllAccounts()
await this._store.dispatch('auth/setAccounts', accounts)
if (accounts.length > 0) {
this._msal.setActiveAccount(accounts[0])
this._msal.acquireTokenSilent(this._loginRequest).then(async (accessTokenResponse) => {
// Acquire token silent success
// Call API with token
// let accessToken = accessTokenResponse.accessToken;
await this._store.dispatch('auth/setResponse', accessTokenResponse)
}).catch((error) => {
Notify.create({
message: JSON.stringify(error),
color: 'red'
})
// Acquire token silent failure, and send an interactive request
if (error.errorMessage.indexOf('interaction_required') !== -1) {
this._msal.acquireTokenPopup(this._loginRequest).then(async (accessTokenResponse) => {
// Acquire token interactive success
await this._store.dispatch('auth/setResponse', accessTokenResponse)
}).catch((error) => {
// Acquire token interactive failure
Notify.create({
message: JSON.stringify(error),
color: 'red'
})
})
}
})
}
}
async login () {
// this._msal.handleRedirectPromise().then((res) => this.handleResponse(res))
// await this._msal.loginRedirect(this._loginRequest)
await this._msal.loginPopup(this._loginRequest).then((resp) => this.handleResponse(resp))
}
async logout () {
await this._store.dispatch('auth/setAccounts', [])
await this._msal.logout()
}
}
// "async" is optional;
// more info on params: https://quasar.dev/quasar-cli/boot-files
export default ({
app,
store,
Vue
}) => {
const msalInstance = new MsalService(
app.appConfig, store
)
Vue.prototype.$msal = msalInstance
app.msal = msalInstance
}
PD:使用类星体框架
感谢Nan Yu I managed to get token that can be validated by any public jwt validator like jwt.io
(无法将我的评论放在 Nan Yu 的回答下的评论部分,因为它太长了)。
据我了解 Nan Yu 提到的 讨论 中的观点,即默认情况下 Azure AD 为 Microsoft Graph 生成令牌,并且这些令牌使用特殊的签名机制,以便无法使用 public 验证器来验证签名(jwt.ms 微软的验证器除外,它很可能知道神秘的 特殊处理 表示 :)).
要获取可以使用 public 验证器验证的不适用于 Microsoft Graph 的访问令牌,我必须:
- 删除任何与 Microsoft Graph 相关的范围(默认情况下我只配置了一个范围
User.Read
所以在 appConfig > API 权限中删除它)
- 为您的应用程序创建一个自定义范围(appConfig > 公开一个 API > 添加范围 ...)这个范围看起来像
api://{application-id}/scope-name
- 在应用程序中添加刚刚创建的范围API权限(appConfig>API权限>添加api权限>我的APIs>select你的申请 > 委托权限 > 检查您的范围 > 添加权限)
- 然后在你的 openid 客户端范围内使用这个范围,在我的例子中我有:
openid offline_access {application-id}/scope-name
Note that in the openid client config newly created scope is used without api:// prefix (offline_access I have to enable refresh_token can be ignored if refresh token mechanism is not used)
我在使用 jwt.io 验证我的 Azure 广告访问令牌时收到无效签名。然而,我的 id 令牌验证得很好!
我已经看到并尝试了
中建议的解决方案
和
https://nicksnettravels.builttoroam.com/post/2017/01/24/Verifying-Azure-Active-Directory-JWT-Tokens.aspx
但都不适用于我的访问令牌。
访问和 Id 令牌是通过 Adal.js:
生成的 var endpoints = {
"https://graph.windows.net": "https://graph.windows.net"
};
var configOptions = {
tenant: "<ad>.onmicrosoft.com", // Optional by default, it sends common
clientId: "<app ID from azure portal>",
postLogoutRedirectUri: window.location.origin,
endpoints: endpoints,
}
window.authContext = new AuthenticationContext(configOptions);
为什么我可以验证我的 ID 令牌,而不是我的访问令牌?
请参考话题:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609
but if look at the Jwt.Header you will see a 'nonce'. This means you need special processing. Normal processing will fail.
因此,如果随机数包含在访问令牌中,使用 JWT.io 或 JwtSecurityToken 验证签名将不会成功。
如果其他人有无效签名错误,您应该查看此评论:https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/521#issuecomment-577400515
解决了我的配置问题。
本质上,如果您正在获取访问令牌来访问您自己的资源服务器而不是 Graph API,您的范围参数应该是 [CLIENT_ID]/.default
(如果您使用访问令牌来访问图 API,您不需要自己验证令牌)
感谢@Antoine,我修复了我的代码。在这里,我将让我个人的 vue.js 插件可供其他人参考:
import { PublicClientApplication } from '@azure/msal-browser'
import { Notify } from 'quasar'
export class MsalService {
_msal = null
_store = null
_loginRequest = null
constructor (appConfig, store) {
this._store = store
this._msal = new PublicClientApplication(
{
auth: {
clientId: appConfig.auth.clientId,
authority: appConfig.auth.authority
},
cache: {
cacheLocation: 'localStorage'
}
})
this._loginRequest = {
scopes: [`${appConfig.auth.clientId}/.default`]
}
}
async handleResponse (response) {
await this._store.dispatch('auth/setResponse', response)
const accounts = this._msal.getAllAccounts()
await this._store.dispatch('auth/setAccounts', accounts)
if (accounts.length > 0) {
this._msal.setActiveAccount(accounts[0])
this._msal.acquireTokenSilent(this._loginRequest).then(async (accessTokenResponse) => {
// Acquire token silent success
// Call API with token
// let accessToken = accessTokenResponse.accessToken;
await this._store.dispatch('auth/setResponse', accessTokenResponse)
}).catch((error) => {
Notify.create({
message: JSON.stringify(error),
color: 'red'
})
// Acquire token silent failure, and send an interactive request
if (error.errorMessage.indexOf('interaction_required') !== -1) {
this._msal.acquireTokenPopup(this._loginRequest).then(async (accessTokenResponse) => {
// Acquire token interactive success
await this._store.dispatch('auth/setResponse', accessTokenResponse)
}).catch((error) => {
// Acquire token interactive failure
Notify.create({
message: JSON.stringify(error),
color: 'red'
})
})
}
})
}
}
async login () {
// this._msal.handleRedirectPromise().then((res) => this.handleResponse(res))
// await this._msal.loginRedirect(this._loginRequest)
await this._msal.loginPopup(this._loginRequest).then((resp) => this.handleResponse(resp))
}
async logout () {
await this._store.dispatch('auth/setAccounts', [])
await this._msal.logout()
}
}
// "async" is optional;
// more info on params: https://quasar.dev/quasar-cli/boot-files
export default ({
app,
store,
Vue
}) => {
const msalInstance = new MsalService(
app.appConfig, store
)
Vue.prototype.$msal = msalInstance
app.msal = msalInstance
}
PD:使用类星体框架
感谢Nan Yu I managed to get token that can be validated by any public jwt validator like jwt.io (无法将我的评论放在 Nan Yu 的回答下的评论部分,因为它太长了)。
据我了解 Nan Yu 提到的 讨论 中的观点,即默认情况下 Azure AD 为 Microsoft Graph 生成令牌,并且这些令牌使用特殊的签名机制,以便无法使用 public 验证器来验证签名(jwt.ms 微软的验证器除外,它很可能知道神秘的 特殊处理 表示 :)).
要获取可以使用 public 验证器验证的不适用于 Microsoft Graph 的访问令牌,我必须:
- 删除任何与 Microsoft Graph 相关的范围(默认情况下我只配置了一个范围
User.Read
所以在 appConfig > API 权限中删除它) - 为您的应用程序创建一个自定义范围(appConfig > 公开一个 API > 添加范围 ...)这个范围看起来像
api://{application-id}/scope-name
- 在应用程序中添加刚刚创建的范围API权限(appConfig>API权限>添加api权限>我的APIs>select你的申请 > 委托权限 > 检查您的范围 > 添加权限)
- 然后在你的 openid 客户端范围内使用这个范围,在我的例子中我有:
openid offline_access {application-id}/scope-name
Note that in the openid client config newly created scope is used without api:// prefix (offline_access I have to enable refresh_token can be ignored if refresh token mechanism is not used)