ventajas riesgos que pueden hacer fraudes firma electronica desventajas con c# asp.net dotnetopenauth

c# - que - riesgos firma electronica



No se puede usar la firma PLAINTEXT con un proveedor de servicios DotNetOpenAuth (2)

Estoy construyendo un servidor de autorizaciones OAuth 1.0(a) usando DotNetOpenAuth (paquete DotNetOpenAuth.OAuth.ServiceProvider, version = 4.1.4.12333 ). El servidor está alojado en una aplicación ASP.NET, pero eso es irrelevante para la pregunta.

My ServiceProvider está configurado de esta manera:

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) ); }

La parte relevante de mi get_request_token final get_request_token ve así:

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

Ahora cuando un consumidor envía la siguiente solicitud a este punto final:

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

(roto por claridad):

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

El método serviceProvider.ReadTokenRequest() arroja una excepción:

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)

Por otro lado, si el cliente envía la siguiente solicitud:

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

(roto por claridad):

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

tiene éxito.

Como puede ver, la única diferencia entre esas 2 solicitudes es el oauth_signature_method está utilizando. En el primer caso se usa PLAINTEXT mientras que en el segundo HMAC-SHA1 .

¿Es posible hacer que DotNetOpenAuth acepte un método de firma PLAINTEXT para el punto final del token de solicitud junto con el verbo GET (incluso si la OAuth 1.0(a) specification recomienda que se utilice POST para este punto final)? ¿Hay alguna opción de configuración que pueda relajar este requisito en el servidor?

Por el momento, modificar al cliente no es una opción para mí.


El siguiente bloque de código puede ayudarlo a generar una firma de texto sin formato

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; }


La autenticación de OAuth se realiza en tres pasos:

  1. El consumidor obtiene un token de solicitud no autorizado.

  2. El usuario autoriza el token de solicitud.

  3. El consumidor intercambia el token de solicitud por un token de acceso.

Así que esto es lo que se vería así:

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 }