我是OAuth的新手,我使用了this教程来生成从客户端应用到目标应用的访问令牌。代码本身可以正常工作,但是在https://jwt.io/
上解码时,我生成的访问令牌具有invalid signature
这是教程中的代码
public class ServicePrincipal
{
/// <summary>
/// The variables below are standard Azure AD terms from our various samples
/// We set these in the Azure Portal for this app for security and to make it easy to change (you can reuse this code in other apps this way)
/// You can name each of these what you want as long as you keep all of this straight
/// </summary>
static string authority = ""; // the AD Authority used for login. For example: https://login.microsoftonline.com/myadnamehere.onmicrosoft.com
static string clientId = ""; // client app's client id
static string clientSecret = ""; // client app's secret key
static string resource = ""; // target app's App ID URL
/// <summary>
/// wrapper that passes the above variables
/// </summary>
/// <returns></returns>
static public async Task<AuthenticationResult> GetS2SAccessTokenForProdMSAAsync()
{
return await GetS2SAccessToken(authority, resource, clientId, clientSecret);
}
static async Task<AuthenticationResult> GetS2SAccessToken(string authority, string resource, string clientId, string clientSecret)
{
var clientCredential = new ClientCredential(clientId, clientSecret);
AuthenticationContext context = new AuthenticationContext(authority, false);
AuthenticationResult authenticationResult = await context.AcquireTokenAsync(
resource, // the resource (app) we are going to access with the token
clientCredential); // the client credentials
return authenticationResult;
}
}
我发现还有另一段代码也可以生成访问令牌:
AuthenticationContext authenticationContext =
new AuthenticationContext({authority});
ClientCredential clientCredential = new ClientCredential({client app id}, {client app secret});
try
{
AuthenticationResult result =
await authenticationContext.AcquireTokenAsync({target app's App ID URL},
clientCredential);
}
catch (Exception e)
{
return false;
}
这两个代码都给了我1.0版的无效签名访问令牌
这里有两个问题:
我注意到,当我解码访问令牌时,它显示"ver": "1.0"
。这是否意味着它正在使用OAuth1.0?因为我想使用OAuth 2.0。为什么代码会生成创建OAuth1.0而不是OAuth2.0的令牌?
为什么签名无效?
答案 0 :(得分:4)
我尝试了与您相同的代码,但情况相同invalid signature
,但是当我将jwt ALGORITHM更改为 HS256 时,我得到了Signature Verified
。
签名:
RRS256和HS256的区别:
RS256 (带有SHA-256的RSA签名)是一种非对称算法,它使用公共/专用密钥对:身份提供者具有用于生成签名的专用(秘密)密钥, JWT的使用者将获得一个公共密钥来验证签名。与公用密钥相比,由于不需要保护公用密钥,因此大多数身份提供者都可以轻松地使它可供消费者获取和使用(通常通过元数据URL)。
另一方面,HS256 (带SHA-256的HMAC)是一种对称算法,只有一个(秘密)密钥在双方之间共享。由于使用相同的密钥来生成签名和验证签名,因此必须注意确保密钥不被破坏。
答案 1 :(得分:1)
您是否将密钥发布到jwt.io的表单中?尝试使用授权标头中的令牌进行真正的休息呼叫。如果一切正常,而jwt却没有,也许是在他们身上。
答案 2 :(得分:1)
我注意到,当我解码访问令牌时,它显示为“ ver”:“ 1.0”。这是否意味着它正在使用OAuth1.0?因为我想使用OAuth 2.0。.为什么代码会生成创建OAuth1.0的令牌而不是OAuth2.0?
您正在使用OAuth2.0,loadGoogleClient = () => {
gapi.load("client:auth2", () => {
gapi.auth2.init({
'client_id': my-client-id,
'apiKey': my-key,
'scope': "https://www.googleapis.com/auth/drive.readonly",
'discoveryDocs': ['https://content.googleapis.com/discovery/v1/apis/drive/v3/rest']
})
// Listen for sign-in state changes.
console.log(`User is signed in: ${gapi.auth2.getAuthInstance().isSignedIn.get()}`);
gapi.client.load("https://content.googleapis.com/discovery/v1/apis/drive/v3/rest")
.then(() => { console.log("GAPI client loaded for API");
}, (error) => { console.error("Error loading GAPI client for API", error);
});
console.log('Init should have worked');
});
}
表示JWT令牌是由Azure AD V1.0端点发行的。
为什么签名无效?
API需要检查JWT标头(属性alg)指定的算法是否与API期望的算法匹配。 AAD使用authGoogle = () => {
gapi.auth2.getAuthInstance()
.signIn({scope: "https://www.googleapis.com/auth/drive.readonly"})
.then(function() { console.log("Sign-in successful"); },
function(err) { console.error("Error signing in", err); });
}
,因此您应更改为ver:"1.0"
:
通常的方法是从模和指数构建,从RS256
匹配的kid和令牌中的x5t中找到它们。任何使用https://play.golang.org/之类的在线工具来获取公钥都由两个部分组成:n和e。您还可以使用RS256
值,单击here进行采样。