通过PHP脚本在基于DotNetOpenAuth的提供商服务上使用OAuth 2.0时获得奇怪的异常和死亡
本文关键字:0时 异常 OAuth 脚本 PHP DotNetOpenAuth 通过 服务 提供商 | 更新日期: 2023-09-27 18:14:52
我通过NuGet使用DotNetOpenAuth 4.3.0.0版本。
我使用下面的教程开发了一个Service Provider。https://github.com/DotNetOpenAuth/DotNetOpenAuth/wiki/Security-scenarios在开发了一个示例Service Provider之后,我用PHP开发了一个简单的网站,它使用OAuth。
<?php
$client_id = 'RP';
$client_secret = 'password';
$callback_url = 'http://localhost/dotnetoauthtester/index.php';
$service_provider_url = 'http://localhost:58883/OAuth/';
$code = $_REQUEST["code"];
if(empty($code)){
$state = '';
$scope = 'http://localhost/some_web_service/';
$auth_url = $service_provider_url.'auth?'
.'client_id='.$client_id
.'&response_type=code'
.'&redirect_uri='.$callback_url
.'&state='.$state
.'&scope='.$scope;
header('Location:'.$auth_url);
exit();
}
$access_token_url = $service_provider_url.'token?'
.'client_id='.$client_id
.'&client_secret='.$client_secret
.'&redirect_uri='.$callback_url
.'&code='.$code
.'&grant_type=authorization_code';
# ___ It returns 400 bad request here. ___
$access_token_array = json_decode(file_get_contents($access_token_url),true);
var_dump($access_token_array);
我的authserverhostipls .cs是这样的。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Web;
using DotNetOpenAuth.OAuth2;
using DotNetOpenAuth.OAuth2.ChannelElements;
using DotNetOpenAuth.OAuth2.Messages;
namespace ServiceProviderTestMvc.Models
{
public class AuthServerHostImpl : IAuthorizationServerHost
{
public IClientDescription GetClient(string clientIdentifier)
{
switch (clientIdentifier)
{
case "RP":
var allowedCallback = "http://localhost/dotnetoauthtester/index.php";
return new ClientDescription("data!", new Uri(allowedCallback), ClientType.Confidential);
}
return null;
}
public bool IsAuthorizationValid(IAuthorizationDescription authorization)
{
if (authorization.ClientIdentifier == "RP"
&& authorization.Scope.Count == 1
&& authorization.Scope.First() == "http://localhost/some_web_service/"
&& authorization.User == "Max muster")
{
return true;
}
return false;
}
public AccessTokenResult CreateAccessToken(IAccessTokenRequest accessTokenRequestMessage)
{
var token = new AuthorizationServerAccessToken();
token.Lifetime = TimeSpan.FromMinutes(10);
var signCert = LoadCert(Config.STS_CERT);
token.AccessTokenSigningKey = (RSACryptoServiceProvider)signCert.PrivateKey;
var encryptCert = LoadCert(Config.SERVICE_CERT);
token.ResourceServerEncryptionKey = (RSACryptoServiceProvider)encryptCert.PublicKey.Key;
var result = new AccessTokenResult(token);
return result;
}
private static X509Certificate2 LoadCert(string thumbprint)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, validOnly: false);
if (certs.Count == 0)
{
throw new Exception("Could not find certification!!");
}
var cert = certs[0];
return cert;
}
public DotNetOpenAuth.Messaging.Bindings.ICryptoKeyStore CryptoKeyStore
{
get
{
return new InMemoryCryptoKeyStore();
}
}
public DotNetOpenAuth.Messaging.Bindings.INonceStore NonceStore
{
get
{
return new DummyNonceStore();
}
}
public AutomatedAuthorizationCheckResponse CheckAuthorizeClientCredentialsGrant(IAccessTokenRequest accessRequest)
{
throw new NotImplementedException();
}
public AutomatedUserAuthorizationCheckResponse CheckAuthorizeResourceOwnerCredentialGrant(string userName, string password, IAccessTokenRequest accessRequest)
{
throw new NotImplementedException();
}
}
}
但是,它在"_"之后的行失败了,它在这里返回400个错误请求。_ "。堆栈跟踪如下所示。
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,393 [33] DEBUG DotNetOpenAuth.Messaging [(null)] - The following required parameters were missing from the DotNetOpenAuth.OAuth2.AuthServer.Messages.AccessTokenRefreshRequestAS message: {refresh_token,
}
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,394 [33] DEBUG DotNetOpenAuth.Messaging [(null)] - The following required parameters were missing from the DotNetOpenAuth.OAuth2.Messages.AccessTokenResourceOwnerPasswordCredentialsRequest message: {username,
password,
}
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,394 [33] DEBUG DotNetOpenAuth.Messaging [(null)] - The following required parameters were missing from the DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationRequest message: {response_type,
}
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,395 [33] DEBUG DotNetOpenAuth.Messaging [(null)] - The following required parameters were missing from the DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationImplicitRequest message: {response_type,
}
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,395 [33] DEBUG DotNetOpenAuth.Messaging [(null)] - The following required parameters were missing from the DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationFailedResponse message: {error,
}
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,396 [33] WARN DotNetOpenAuth.Messaging [(null)] - Multiple message types seemed to fit the incoming data: {AccessTokenAuthorizationCodeRequestAS (2.0),
AccessTokenClientCredentialsRequest (2.0),
}
DotNetOpenAuth.Messaging: 2013-05-23 14:08:47,397 [33] ERROR DotNetOpenAuth.Messaging [(null)] - Protocol error: 'AccessTokenAuthorizationCodeRequestAS' messages cannot be received with HTTP verb 'GetRequest'.
at DotNetOpenAuth.Messaging.ErrorUtilities.VerifyProtocol(Boolean condition, String unformattedMessage, Object[] args)
at DotNetOpenAuth.Messaging.Channel.Receive(Dictionary2 fields, MessageReceivingEndpoint recipient)
at DotNetOpenAuth.Messaging.Channel.ReadFromRequestCore(HttpRequestBase request)
at DotNetOpenAuth.OAuth2.ChannelElements.OAuth2AuthorizationServerChannel.ReadFromRequestCore(HttpRequestBase request)
at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestBase httpRequest)
at DotNetOpenAuth.Messaging.Channel.TryReadFromRequest[TRequest](HttpRequestBase httpRequest, TRequest& request)
at DotNetOpenAuth.OAuth2.AuthorizationServer.HandleTokenRequest(HttpRequestBase request)
at ServiceProviderTestMvc.Controllers.OAuthController.Token()
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass81.b__7(IAsyncResult )
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c_DisplayClass25.<>c__DisplayClass2a.b__20()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.b__22(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End()
at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.b__3(IAsyncResult ar)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End()
at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__3(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End()
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
对"code"令牌的第一个请求应该使用GET请求。对"访问令牌"的后续请求应该使用POST请求进行。根据堆栈跟踪错误,看起来您对访问令牌的请求是GET请求,请尝试post该请求,即
$postdata = http_build_query(
array(
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $callback_url,
'code' => $code,
'grant_type' => 'authorization_code'
));
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
));
$context = stream_context_create($opts);
$result = file_get_contents($service_provider_url.'token', false, $context);
上面的代码只是一个建议,没有经过测试。
好运