How to get token from JWE Encrypt method of Jose Sdk - c#

I am new in C# jose jwt. I have been using JWE.Encrypt() method.
AnyJson anyJson = new AnyJson();
anyJson.page = 2;
anyJson.filters = new Filters();
anyJson.filters.startDate = DateTime.Now.Date;
anyJson.filters.endDate = DateTime.Now.Date;
string key = "bXF9p18KmVjgyzv3lP6otbne1W8PLo6gEE287SMyjeI=";
var payload = Newtonsoft.Json.JsonConvert.SerializeObject(anyJson);
string token = JWE.Encrypt(payload,
new[] { new JweRecipient(JweAlgorithm.A256KW, Convert.FromBase64String(key), null) },
JweEncryption.A256GCM);
and I am getting response in json like
{"ciphertext":"PwUATwt8xgGNSh7V2BjhOtlb0rC_GpFKyKWYdx2Fum6SpY6R9TWnH2BPPbK5qJ8_A0Q9MBkbjJkV4vi_CdKPXI1HXKiFmhxtX34pktiWuP-3ggXEMe1BZV--Lz40xRB9FyDgQ9S_SdDlgC6QMNVBQMCjtiKyhFSwIT5Qwb8AZGlew5cd7AVXhcpXAofMdF1ZV8t8JfpmqJe2ucZW06_aaFe9V3bNn9S5bv9b","protected":"eyJlbmMiOiJBMjU2R0NNIn0","iv":"8MD-0rHQDoIEmRXp","tag":"9DNgPKWMfA2jBBehA5IMxQ","header":{"alg":"A256KW"},"encrypted_key":"GXZKICb9L7EP91DQ2bJod3WNOaVjkSjzBcIsH6gk0vECpUwyTNasEw"}
but as per the doc given by client, we need to send this JWE token like
{ "request": {"Token": "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.Hwv8rJUIcWzZgfAe1g8QaXrcczAx2-lvQX0gighE8OPg6L8-L9YyikY4Xx2oWUr2mbsHnS7nbT1dJ59Nz-CpdUk5JwC--Qml.e1rlkqkDbe3yRusnTiDzMw.ddSHOBVCIpU4-jSCqpGbtAsOuDBJnjnP4xFU97TeBOghlk3quvTd0lvkunDNvKOSqlw0zi2Gtz9Y4lZNPVEyYTkqGprjqMFGulcI_0gKzyu7CaFzJjWBicspIo81ljPdwkodNnfjwnuGjEIj5UUgJHcebEaFNDVqgU4Gtsvn9g7LOHVhmGXLOzlNcRbbgp.SQqu8k5C7QoYP0uXSV6H42zb3Ft9ehSfZGzPrUE6vVw"}}
which is looks like JSON. How can I send data like this?

Are you really sure you should sent a JWT token that you create your self?
typically a JSON token is issued by an authorization service. That both you and the receiver of the token trusts.

Related

ASP.Net Core 3.1 Identity - Generating Password Reset Token Issue

I am developing a site where the users will be able to click a "Forgot My Password" button to reset their passwords.
Currently, once the email has been validated, the following code should generate a token to be emailed to the user:
if(validUser != null)
{
var generationTime = DateTime.Now;
var pwToken = await _userManager.GeneratePasswordResetTokenAsync(validUser);
await _userManager.UpdateAsync(validUser);
var url = $"https://{Request.Host}/verify/{HttpUtility.UrlEncode(pwToken)}";
//EmailHelper.SendMagicLinkEmail(validUser, url, Request);
return new RedirectResult("/");
}
All information online regarding this seems to suggest that this is the way to do things. I have set up the Default token providers in the Startup.csfile too:
identityOptions: o => {
o.User.RequireUniqueEmail = true;
o.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultProvider;
o.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultProvider;
},
Yet when a token is generated it produces a large token such as this:
CfDJ8CnvAYtZf+1IjXpKUM7+umDYEaImg2SPFglPX3Y8RmYpEfg5zpK8xL54lvlbJUd54CaIzzYlff/GU+xKKS8mmG5UdC1zdk24nOsJNpIlmC3P5V72BchS4P9DGFTR77XiKbMAAYymnMomS2zCdTKh+E4bn9RI6FVinMecG1HR7nSHmOI2McbXHBFTanI/0uwxH5WI/Dj4AFTBP39ni7mfKkeWz2nJ5pTemELJJ6pYP50+
The problem here is obviously the forward slashes, which cause issues with routing so are encoded out here:
var url = $"https://{Request.Host}/verify/{HttpUtility.UrlEncode(pwToken)}";
The problem is that even with that, .Net Core seems to un-encode it and produce the following error when the generated link is accessed:
This error isn't necessarily the issue, and I do understand it's importance. Yet I can't seem to find any explanation as to why this token is behaving this way. All online examples seem to produce a fairly standard GUID style token, not something such as this.
Does anyone know why this might be happening?
Cheers
You may want to try the Url.Action() method:
Example:
var token = userManager.GeneratePasswordResetTokenAsync(user).Result;
var resetLink = Url.Action("ResetPassword","Account", new { token = token }, protocol: HttpContext.Request.Scheme);
var message = "Click here to reset your password";
//Then send your message to the user
Note in the example above the email must be HTML for the link to work
The token looks fairly normal to me.
I think the URL encoding method you'd want to use is Uri.EscapeDataString. What I've personally done is using a UriBuilder and escaped the query string values (in this case for email confirmation):
var uriBuilder = new UriBuilder
{
Scheme = "https",
Host = "my.website.com",
Path = "/confirmEmail",
Query = $"email={Uri.EscapeDataString(email)}&token={Uri.EscapeDataString(token)}"
};
var fullUrl = uriBuilder.Uri.AbsoluteUri;
For you that'd be:
var uriBuilder = new UriBuilder
{
Scheme = "https",
Host = Request.Host,
Path = $"/verify/{Uri.EscapeDataString(pwToken)}"
};
var fullUrl = uriBuilder.Uri.AbsoluteUri;

INVALID_REQUEST_BODY Error calling ListStatusAsync using C# DocuSign SDK

I am using C# DocuSign SDK. I am simply trying to retrieve Envelopes, so using EnvelopesApi.ListStatusAsync. Like this:
EnvelopesApi envelopeApi = new EnvelopesApi(ApiClient.Configuration);
var options = new ListStatusOptions();
var date = DateTime.Now.AddDays(-30);
options.fromDate = date.ToString("yyyy/MM/dd");
var envelopesList = envelopeApi.ListStatusAsync(AccountId, null, options);
Response:
Error calling ListStatus:
{
"errorCode": "INVALID_REQUEST_BODY",
"message": "The request body is missing or improperly formatted."
}
Fiddler shows a 400. I can see Access Token is included in the request (Bearer Authorization Header), so no issues there. Fiddler shows PUT request:
https://demo.docusign.net/restapi/v2.1/accounts/[Account_ID_Guid]/envelopes/status?from_date=2019%2f12%2f14
Basically, this is code retrieved from: https://github.com/docusign/qs-csharp. Only difference is using ListStatusAsync instead of ListStatus. Am I missing something related to Body?
Your code doesn't quite match what the QuickStart example does. In the QS, the method used is ListStatusChanges, not ListStatus.
Try this to get a list of envelopes from the past 30 days:
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient.Configuration);
var options = new EnvelopesApi.ListStatusChangesOptions();
var date = DateTime.Now.AddDays(-30);
options.fromDate = date.ToString("yyyy/MM/dd");
var envelopesList = envelopesApi.ListStatusChanges(accountId, options);
var envelopesListFromAsync = envelopesApi.ListStatusChangesAsync(accountId, options);

How to create CallCredentials from SslCredentials and token string

I am porting a gRPC client from python to c#. Both the python client and the c# client are using the gRPC Framework from grpc.io.
The python client uses the following code to open a secure, non-authenticated channel, which it then uses to procure a token string, which it then uses to create call credentials with the grpc.composite_channel_credentials() function:
channel = grpc.secure_channel(url_server_address, ssl_creds)
stub = gateway.GatewayStub(channel)
# Acquire access token via password authentication
pw_cmd = gateway.PasswordAuthenticateCmd(account_name=url.username, password=url.password)
auth_rsp = stub.PasswordAuthenticate(pw_cmd)
# Open a secure, authenticated channel
auth_creds = grpc.access_token_call_credentials(auth_rsp.access_token)
composite_creds = grpc.composite_channel_credentials(ssl_creds, auth_creds)
channel = grpc.secure_channel(url_server_address, composite_creds)
stub = gateway.GatewayStub(channel)
In c#, I have been able to compile the protocol buffer definitions, and connect with the generated client to successfully acquire the access token:
SslCredentials secureChannel = new SslCredentials(File.ReadAllText(SSLCertificatePath));
Channel channel = new Channel(ServerURL, PortNum, secureChannel);
var client = new GrpcClient(new Grpc.Gateway.GatewayClient(channel));
var response = client.client.PasswordAuthenticate(new PasswordAuthenticateCmd() { AccountName = UserName, Password = UserPassword });
Console.WriteLine(response.AccessToken);
From here, however, I can't find the c# analog to the grpc.composite_channel_credentials() function to take the SslCredentials and the access token string to create combined credentials.
None of the examples here https://grpc.io/docs/guides/auth.html here use a token string, and I haven't been able to find any other examples out there.
What you're looking for is:
https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Core/CallCredentials.cs#L49 and https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Core/ChannelCredentials.cs#L67.
Feel free to also look at:
https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs#L58
I solved my problem using CallCredentials.FromInterceptor().
The grpc.access_token_call_credentials() python call adds an authorization entry to the metadata, and sets its value to "Bearer " + AccessToken, so I just had to do the same:
SslCredentials secureCredentials = new SslCredentials(File.ReadAllText(SSLCertificatePath));
Channel secureChannel = new Channel(ServerURL, PortNum, secureCredentials);
var client = new GrpcClient(new Grpc.Gateway.GatewayClient(secureChannel));
var response = client.client.PasswordAuthenticate(new PasswordAuthenticateCmd() { AccountName = UserName, Password = UserPassword });
var accessTokenCredentials = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) =>
{
metadata.Add("authorization", "Bearer " + passwordResponse.AccessToken);
return TaskUtils.CompletedTask;
}));
var authenticatedCredentials = ChannelCredentials.Create(secureCredentials, accessTokenCredentials);
Channel authenticatedChannel = new Channel(hostURL, hostPort, authenticatedCredentials);
As Jan pointed out in his answer, there is a function in the Grpc.Auth namespace that does the same thing as the function that I wrote: https://github.com/grpc/grpc/blob/c5311260fd923079637f5d43bd410ba6de740443/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs#L58

How to post Twitter message to authenticated user's timeline via OAuth

I've been wrestling with the Twitter API for a few days now but I cannot post a message to an authenticated user's timeline. I've got an ASP.NET MVC 4 application that signs a user in via Twitter and saves the access token that comes back from the sign in process. That part works fine. I can see my application with read and write permissions within the authenticated user's twitter account.
I'm then using that access token, along with the consumer key, consumer secret and oauth token secret associated with my Twitter application, to post to the user's timeline. I'm getting a 401 unauthorised error every time. I've tried using the 1.1 API and the 1 API with the same result.
Most of the code comes from Gary Short's article here: http://garyshortblog.wordpress.com/2011/02/11/a-twitter-oauth-example-in-c/
Here's what I've got so far. If anyone can spot any clues as to what I'm missing I'd be most grateful.
public async Task<bool> Push(TwitterMessage twitterMessage)
{
const string updateApi = "http://api.twitter.com/1/statuses/update.json";
const string oauthConsumerKey = "<consumerKey>";
const string consumerSecret = "<consumerSecret>";
const string oauthSignatureMethod = "HMAC-SHA1";
const string oauthTokenSecret = "<tokenSecret>";
var signingKey = string.Format("{0}&{1}", consumerSecret.Escaped(), oauthTokenSecret.Escaped());
var postBody = "status=" + Uri.EscapeDataString(twitterMessage.MessageContent);
var oauthNonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
var oauthToken = "<authenticatedUserToken>";
var timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
var oauthTimestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
var message = string.Format("POST {0}?{1} HTTP/1.1", updateApi, postBody.Escaped());
var hasher = new HMACSHA1(new ASCIIEncoding().GetBytes(signingKey));
var signatureString = Convert.ToBase64String(hasher.ComputeHash(new ASCIIEncoding().GetBytes(message)));
ServicePointManager.Expect100Continue = false;
var request = (HttpWebRequest)WebRequest.Create(updateApi);
request.KeepAlive = false;
var authorisationBuilder = new StringBuilder();
authorisationBuilder.Append("OAuth ");
authorisationBuilder.AppendFormat("oauth_consumer_key=\"{0}\",", oauthConsumerKey.Escaped());
authorisationBuilder.AppendFormat("oauth_signature_method=\"{0}\",", oauthSignatureMethod.Escaped());
authorisationBuilder.AppendFormat("oauth_timestamp=\"{0}\",", oauthTimestamp.Escaped());
authorisationBuilder.AppendFormat("oauth_nonce=\"{0}\",", oauthNonce.Escaped());
authorisationBuilder.AppendFormat("oauth_token=\"{0}\",", oauthToken.Escaped());
authorisationBuilder.AppendFormat("oauth_signature=\"{0}\"", signatureString.Escaped());
var authorisation = authorisationBuilder.ToString();
request.Headers.Add("Authorization", authorisation);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (var stream = await request.GetRequestStreamAsync())
{
var bodyBytes = new ASCIIEncoding().GetBytes(postBody);
stream.Write(bodyBytes, 0, bodyBytes.Length);
}
//Allow us a reasonable timeout in case Twitter's busy
request.Timeout = 3 * 60 * 1000;
try
{
var response = await request.GetResponseAsync() as HttpWebResponse;
return true;
}
catch (WebException)
{
return false;
}
}
public static string Escaped(this string input)
{
return Uri.EscapeDataString(input);
}
UPDATE Looking at this SO post it looks like I can't use the DotNetOpenAuth twitter client for authorisation, which I had been doing. The suggestion there is to extend the twitter consumer class instead to perform the authorisation, which will allow me to retrieve the user's token secret (the missing piece of my puzzle I think). Will post another update when I get this working.
Check this code and link/article simple and easy :
protected void btnTweet_Click(object sender, EventArgs e)
{
string oauthAccessToken = Session["twtoken"].ToString();
string oauthAccessTokenSecret = Session["twsecret"].ToString();
OAuthHelper oauthhelper = new OAuthHelper();
oauthhelper.TweetOnBehalfOf(oauthAccessToken, oauthAccessTokenSecret, txtTweet.Text);
if (string.IsNullOrEmpty(oauthhelper.oauth_error))
Response.Write("Twit Posted Successfully");
else
Response.Write(oauthhelper.oauth_error);
}
Read more how to get access token and secret key and download OAuthHelper and OAuthUtility Class below is the link -
How to post tweet on behalf of an user from asp.net using oauth authentication
Login with twitter using oauth authentication in asp.net and get access token, screen name and userid
So the problem is an issue with DotNetOpenAuth as it currently stands. For Twitter authentication, the DotNetOpenAuth client doesn't allow for the full authorisation flow (needed for posting to a user's timeline). Only the access token is retrieved from the initial handshake and not the access token secret. I was using the access token secret associated with my Twitter app, rather than the Twitter user who was signing in, so authorisation was failing every time.
UPDATE: I've finally gone with using Daniel Crenna's Tweetsharp library, which makes the code a little simpler than writing my own API wrapper would have been:
public async Task<bool> Push(TwitterAccount account)
{
var twitterService = new TwitterService(consumerKey, consumerSecret);
twitterService.AuthenticateWith(account.AccessToken, account.AccessTokenSecret);
var options = new SendTweetOptions {Status = string.Format("{0} {1}", account.Message.MessageContent, account.Message.ShortLink)};
var status = twitterService.SendTweet(options);
return status != null;
}

What is the verifier in DotNetOpenAuth's DesktopConsumer ProcessUserAuthorization?

I am new to DotNetOpenAuth and I can't find what value to use as the verifier in ProcessUserAuthorization.
What I want to achieve is to log in with my user credentials into an application (called UserVoice) that uses OAuth. Here's what my code looks like:
string requestToken;
var authorizeUri = consumer.RequestUserAuthorization(new Dictionary<string, string>(), null, out requestToken).AbsoluteUri;
var verifier = "???";
var accessToken = consumer.ProcessUserAuthorization(requestToken, verifier).AccessToken;
consumer.PrepareAuthorizedRequest(endpoint, accessToken, data).GetResponse();
I tried to use my username, my password, my consumer key, my consumer secret, but nothing seems to work. Does someone know which value I should use as the verifier?
Thanks
I finally found a way to log in to UserVoice with DotNetOpenAuth. I think UserVoice's implementation of OAuth wasn't standard, but I was able to do it during this:
var consumer = new DesktopConsumer(this.GetInitialServiceDescription(), this._manager)
string requestToken;
consumer.RequestUserAuthorization(null, null, out requestToken);
// get authentication token
var extraParameters = new Dictionary<string, string>
{
{ "email", this._email },
{ "password", this._password },
{ "request_token", requestToken },
};
consumer = new DesktopConsumer(this.GetSecondaryServiceDescription(), this._manager);
consumer.RequestUserAuthorization(extraParameters, null, out requestToken);
Where GetInitialServiceDescription returns the good request description, and GetSecondaryServiceDescription is a hacked version and returns the authorize endpoint in place of the request token endpoint. The "request_token" returned this way (which is not really a normal request_token from my understanding of OAuth) can then be used as an access token for PrepareAuthorizedRequest.
The verifier is the code that UserVoice would display onscreen after the user has said they want to authorize your app. The user must copy and paste this verifier code from the web site back into your application's GUI, so that it can then pass it into the ProcessUserAuthorization method.
This is only required in OAuth 1.0a (not 1.0), and is there to mitigate certain exploitable attacks that were discovered in 1.0. In your ServiceProviderDescription be sure you specify that the service is a 1.0a version (if in fact Uservoice supports that) so that DNOA will communicate to Uservoice that it should create a verifier code.
Incidentally, various tricks including scanning process titles or hosting the browser within your own app can eliminate the manual user copying the verify code step by having your app automatically copy it for him.
The verifier is also used when the Authorization is done via WebAPI and you do not have a redirect displayed in a browser. In this you just send your AuthentificationRequest via code and get the verifier as a json-string without any user interaction.
In this case the process (for OAuth 1.0) looks as follows:
public void AccessAPI ()
{
InMemoryOAuthTokenManager tokenManager = InMemoryOAuthTokenManager(YOUR_CLIENT_KEY, YOUR_CLIENT_SECRET);
var consumer = new DesktopConsumer(GetAuthServerDescription(), tokenManager);
// Get Request token
string requestToken;
var parameters = new Dictionary<string, string>();
parameters["email"] = "foo";
parameters["password"] = "bar";
Uri authorizationUrl = consumer.RequestUserAuthorization(null, parameters, out requestToken);
// Authorize and get a verifier (No OAuth Header necessary for the API I wanted to access)
var request = WebRequest.Create(authorizationUrl) as HttpWebRequest;
request.Method = "Get";
request.Accept = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2";
var response = request.GetResponse() as HttpWebResponse;
string verifier = new StreamReader(response.GetResponseStream()).ReadToEnd().Split('=')[1]; //Irgendwie will Json nicht parsen
// Use verifier to get the final AccessToken
AuthorizedTokenResponse authorizationResponse = consumer.ProcessUserAuthorization(requestToken, verifier);
string accessToken = authorizationResponse.AccessToken;
// Access Ressources
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
var resourceEndpoint = new MessageReceivingEndpoint("https://api.discovergy.com/public/v1/meters", resourceHttpMethod);
using (IncomingWebResponse resourceResponse = consumer.PrepareAuthorizedRequestAndSend(resourceEndpoint, accessToken))
{
string result = resourceResponse.GetResponseReader().ReadToEnd();
dynamic content = JObject.Parse(result);
}
}
private ServiceProviderDescription GetAuthServerDescription()
{
var authServerDescription = new ServiceProviderDescription();
authServerDescription.RequestTokenEndpoint = new MessageReceivingEndpoint(YOUR_REQUEST_ENDPOINT, HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
authServerDescription.UserAuthorizationEndpoint = new MessageReceivingEndpoint(YOUR_AUTHORIZATION_ENDPOINT, HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
authServerDescription.AccessTokenEndpoint = new MessageReceivingEndpoint(YOUR_TOKEN_ENDPOINT, HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
authServerDescription.ProtocolVersion = ProtocolVersion.V10;
authServerDescription.TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() };
return authServerDescription;
}

Categories