Programing

DotNetOpenAuth ServiceProvider에서 PLAINTEXT 서명을 사용할 수 없습니다.

crosscheck 2020. 11. 6. 07:50
반응형

DotNetOpenAuth ServiceProvider에서 PLAINTEXT 서명을 사용할 수 없습니다.


(NuGet 패키지 )를 OAuth 1.0(a)사용하여 권한 부여 서버를 구축하고 있습니다. 서버는 ASP.NET 응용 프로그램에서 호스팅되지만 질문과 관련이 없습니다.DotNetOpenAuthDotNetOpenAuth.OAuth.ServiceProvider, version = 4.1.4.12333

My ServiceProvider는 다음과 같이 구성됩니다.

private ServiceProvider GetServiceProvider()
{
    var baseUri = "http://myauth.com";
    return new ServiceProvider(
        new ServiceProviderDescription
        {
            UserAuthorizationEndpoint = new MessageReceivingEndpoint(
                new Uri(baseUri + "/get_request_token"), 
                HttpDeliveryMethods.GetRequest
            ),
            RequestTokenEndpoint = new MessageReceivingEndpoint(
                new Uri(baseUri + "/authorize"), 
                HttpDeliveryMethods.PostRequest
            ),
            AccessTokenEndpoint = new MessageReceivingEndpoint(
                new Uri(baseUri + "/get_token"), 
                HttpDeliveryMethods.PostRequest
            ),
            ProtocolVersion = ProtocolVersion.V10a,
            TamperProtectionElements = new ITamperProtectionChannelBindingElement[] 
            {
                new PlaintextSigningBindingElement(),
                new HmacSha1SigningBindingElement(),
            },
        },
        tokenManager,
        new OAuthServiceProviderMessageFactory(tokenManager)
    );
}

get_request_token엔드 포인트 의 관련 부분은 다음과 같습니다.

var serviceProvider = GetServiceProvider();
var tokenRequest = serviceProvider.ReadTokenRequest();

이제 소비자가이 끝점에 다음 요청을 보낼 때 :

GET /get_request_token?oauth_nonce=C5657420BCE5F3224914304376B5334696B09B7FFC17C105A7F9629A008869DC&oauth_timestamp=1356006599&oauth_consumer_key=sampleconsumer&oauth_signature_method=plaintext&oauth_signature=samplesecret%26&oauth_version=1.0&oauth_callback=http%3a%2f%2flocalhost%3a30103%2fCustomOAuth1 HTTP/1.1

Host: localhost:8180
Connection: close

(명확성을 위해 깨짐) :

oauth_nonce=C5657420BCE5F3224914304376B5334696B09B7FFC17C105A7F9629A008869DC
oauth_timestamp=1356006599
oauth_consumer_key=sampleconsumer
oauth_signature_method=plaintext
oauth_signature=samplesecret%26
oauth_version=1.0
oauth_callback=http%3a%2f%2flocalhost%3a30103%2fCustomOAuth1

serviceProvider.ReadTokenRequest()메서드는 예외를 throw합니다.

The UnauthorizedTokenRequest message required protections {All} but the channel could only apply {Expiration, ReplayProtection}.
   at DotNetOpenAuth.Messaging.Channel.ProcessIncomingMessage(IProtocolMessage message)
   at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestBase httpRequest)
   at DotNetOpenAuth.Messaging.Channel.TryReadFromRequest[TRequest](HttpRequestBase httpRequest, TRequest& request)
   at DotNetOpenAuth.OAuth.ServiceProvider.ReadTokenRequest(HttpRequestBase request)
   at DotNetOpenAuth.OAuth.ServiceProvider.ReadTokenRequest()
   at OAuthServers.OAuth1.Services.OAuth1Service.Any(GetRequestTokenRequest request)
   at lambda_method(Closure , Object , Object )
   at ServiceStack.ServiceHost.ServiceRunner`1.Execute(IRequestContext requestContext, Object instance, TRequest request)

반면에 클라이언트가 다음 요청을 보내는 경우 :

GET /get_request_token?oauth_callback=http%3a%2f%2flocalhost%3a65271%2foauth1%2fHandleAccessToken&oauth_consumer_key=sampleconsumer&oauth_nonce=rGFvxlWm&oauth_signature_method=HMAC-SHA1&oauth_signature=HV%2f5Vq%2b0cF3NrtiISE9k4jmgCrY%3d&oauth_version=1.0&oauth_timestamp=1356007830 HTTP/1.1

Host: localhost:8180
Connection: close

(명확성을 위해 깨짐) :

oauth_callback=http%3a%2f%2flocalhost%3a65271%2foauth1%2fHandleAccessToken
oauth_consumer_key=sampleconsumer
oauth_nonce=rGFvxlWm
oauth_signature_method=HMAC-SHA1
oauth_signature=HV%2f5Vq%2b0cF3NrtiISE9k4jmgCrY%3d
oauth_version=1.0
oauth_timestamp=1356007830

성공합니다.

보시다시피 두 요청의 유일한 차이점 oauth_signature_method은 사용되는 것입니다. 첫 번째 경우 PLAINTEXT에는 사용되는 반면 두 번째 경우에는 HMAC-SHA1.

DotNetOpenAuth PLAINTEXT가 GET 동사와 함께 요청 토큰 끝점에 대한 서명 방법을 수락하도록 OAuth 1.0(a) specification할 수 있습니까 (이 끝점에 POST를 사용 하도록 권장 하더라도 )? 서버에서이 요구 사항을 완화 할 수있는 구성 옵션 이 있습니까?

현재 클라이언트를 수정하는 것은 나에게 옵션이 아닙니다.


OAuth 인증은 세 단계로 수행됩니다.

  1. 소비자가 무단 요청 토큰을 얻습니다.

  2. 사용자는 요청 토큰을 승인합니다.

  3. 소비자는 요청 토큰을 액세스 토큰으로 교환합니다.

따라서 다음과 같이 표시됩니다.

public class InMemoryTokenManager : IConsumerTokenManager, IOpenIdOAuthTokenManager
{
private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();

public InMemoryTokenManager(string consumerKey, string consumerSecret)
{
    if (String.IsNullOrEmpty(consumerKey))
    {
        throw new ArgumentNullException("consumerKey");
    }

    this.ConsumerKey = consumerKey;
    this.ConsumerSecret = consumerSecret;
}

public string ConsumerKey { get; private set; }

public string ConsumerSecret { get; private set; }

#region ITokenManager Members

public string GetConsumerSecret(string consumerKey)
{
    if (consumerKey == this.ConsumerKey)
    {
        return this.ConsumerSecret;
    }
    else
    {
        throw new ArgumentException("Unrecognized consumer key.", "consumerKey");
    }
}

public string GetTokenSecret(string token)
{
    return this.tokensAndSecrets[token];
}

public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response)
{
    this.tokensAndSecrets[response.Token] = response.TokenSecret;
}

public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret)
{
    this.tokensAndSecrets.Remove(requestToken);
    this.tokensAndSecrets[accessToken] = accessTokenSecret;
}

/// <summary>
/// Classifies a token as a request token or an access token.
/// </summary>
/// <param name="token">The token to classify.</param>
/// <returns>Request or Access token, or invalid if the token is not recognized.</returns>
public TokenType GetTokenType(string token)
{
    throw new NotImplementedException();
}

#endregion

#region IOpenIdOAuthTokenManager Members

public void StoreOpenIdAuthorizedRequestToken(string consumerKey, AuthorizationApprovedResponse authorization)
{
    this.tokensAndSecrets[authorization.RequestToken] = string.Empty;
}

#endregion
}

다음 코드 블록은 일반 텍스트 서명을 생성하는 데 도움이 될 수 있습니다.

public static string GetSignature(OAuthSignatureMethod signatureMethod,             AuthSignatureTreatment signatureTreatment, string signatureBase, string consumerSecret, string tokenSecret)
{
    if (tokenSecret.IsNullOrBlank())
    {
        tokenSecret = String.Empty;
    }

    consumerSecret = UrlEncodeRelaxed(consumerSecret);
    tokenSecret = UrlEncodeRelaxed(tokenSecret);

    string signature;
    switch (signatureMethod)
    {
        case OAuthSignatureMethod.HmacSha1:
        {
            var crypto = new HMACSHA1();
            var key = "{0}&{1}".FormatWith(consumerSecret, tokenSecret);

            crypto.Key = _encoding.GetBytes(key);
            signature = signatureBase.HashWith(crypto);

            break;
        }
        case OAuthSignatureMethod.PlainText:
        {
            signature = "{0}&{1}".FormatWith(consumerSecret, tokenSecret);

            break;
        }
        default:
            throw new NotImplementedException("Only HMAC-SHA1 is currently supported.");
        }

        var result = signatureTreatment == OAuthSignatureTreatment.Escaped
            ? UrlEncodeRelaxed(signature)
            : signature;

        return result;
    }

참고 URL : https://stackoverflow.com/questions/13972898/unable-to-use-plaintext-signature-with-a-dotnetopenauth-serviceprovider

반응형