I have got the access token as a response from the server in Oauth2.0, but i am not able to fetch it into my code. Could anybody help me giving the code in C# or help just giving some part of it?
var uri = new Uri("http://176.66.102.44:8088/#access_token=eHwAIJd%40bo657tdv8XSaS6hYU%40Ov/XiOWBlMdwo4/h63Q1E%40RcJukIbBnDU%40dh/AYJnEQc4/WmTrUCN3snAntvmchEpZ244LiSIexX/Xiw5jxhR0MkNcS0Y/4bx7Qq4Ws3Wmy3bhFbPSmZQh1KRINwOzY32d8Xz72LGwm8VwyFCn9U1Yo8ERan21EKDvcQpdR%40b4/bDm5eRwIbga0hm7Wog7LnDsQ/OggJqP9CMMkZbqMRN881H4sw0ebMfSZyZf448/HIX5Smfr1%409ofCPzQrZ5GpFVCsaftczTiN%40TnVRPsArbUeLDM2eIAXZyd/QbnBTU840UU3KJ0ohvlBvMi7mYgj0u76JTqRqvyjVnqdNQX6yEPu/6F6SUxEaGkcTRp4h9sVTRZ%40aEMMoQ/0p73GahSPB/G6wuJOfT5PBopnSBrspJq5CvCH2dnz5STkc4ZhpUjj2SLxBDxiJLVruNSbri3sY~&token_type=Bearer&expires_in=120");
var fragments = uri.Fragment.Split('&');
string accessToken = null;
if (fragments.Length > 0 && fragments[0].StartsWith("#access_token="))
{
accessToken = fragments[0].Remove(0, "#access_token=".Length);
}
if (accessToken != null)
{
// Do something with the token
}
How this works is we are going to use the Uri class to parse the Url for us.
The Uri class property Fragment will retrieve everything after (and including) the #, as described in the docs.
We will split on the ampersand because we only need the access_token parameter. We don't need token_type or expires_in. We'll ignore those.
The last part is just throwing the excess data away on the string which is the part that says "#access_token=" so we call Remove on the string to do that. This returns a new string to accessToken and then you can do whatever you want with the data.
Also, keep in mind this only works if the access_token is the first part of the fragment. If it's isn't then after you do the Split you'll need to see which index of the array starts with "access_token=" instead
Uri Class
Uri.Fragment Property Info
Related
I wrote this code in a C# ASP.NET Core Web API project:
[HttpGet]
[Route("GetShortURL/{_url}/{tokenPass}")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
When I enter this parameter as _url, I get an error:
Error: Not Found
https://github.com/VahidN/DNTPersianUtils.Core
http://...//GetShortURL/https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core/TokenPass
How can I call this API with the first Web URL parameter?
when i change the [Route("GetShortURL/{_url}/{tokenPass}")] to [Route("GetShortURL")] the problem was solved but i want to send query by / not by ?
for example, i want to call API like this :
1- http://..../GetShortURL/_UrlParam/_TokenPassParam
not like below :
2- http://..../GetShortURL?_url=_urlParam&tokenPass=_TokenPassParam
the second way works fine but I want first way to work correctly when i pass an URL like this
https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core
can anyone help me?
First approach:
Pass the params you want as query string and then change the method like below:
[HttpGet("GetShortURL")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
Then For extracting the different parts of the url (protocol, domain name, path and query string), use the code below (path is an array separated by slash):
try
{
var decodedUrl = System.Web.HttpUtility.UrlDecode(_url);
Uri uri = new Uri(decodedUrl);
var scheme = uri.Scheme;
var host = uri.Host;
var absolutePathSeperatedBySlash = uri.AbsolutePath.Split('/').Skip(1).ToList();
var query = uri.Query;
// rest of the code ...
}
catch (Exception ex)
{
//...
}
Second approach:
If you want it to be sent as a url parameter, first you have to encode the value of _url with encodeURIComponent() in javascript, to make sure that some special characters like , / ? : # & = + $ # are changed.
Then:
[HttpGet("GetShortURL/{_url}/{tokenPass}")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
The rest is just like the method body of the first approach.
With the following url
http://...//GetShortURL/https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core/TokenPass
The value of _url will be:
If you want to convert it to a correct url,you needs to replace %2F with / in GetShortURL:
var url = _url.Replace("%2F","/");
just make parameters to be optional
[HttpGet("GetShortURL/{_url?}/{tokenPass?}")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
in this case you can call the action without any parameters, with one parameter or with two parameters
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;
I am trying to write some simple tests User Authentication mechanism which uses Basic Authentication. How can I retrieve the credentials from the header?
string authorizationHeader = this.HttpContext.Request.Headers["Authorization"];
Where do I go from here? There are several tutorials but I new to .NET and authentication, could you explain in your answer exactly step-by-step the what and why you are doing.
From my blog:
This will explain in detail how this all works:
Step 1 - Understanding Basic Authentication
Whenever you use Basic Authentication a header is added to HTTP Request and it will look similar to this:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Source: http://en.wikipedia.org/wiki/Basic_access_authentication
"QWxhZGRpbjpvcGVuIHNlc2FtZQ==" is just "username:password" encoded in Base64(http://en.wikipedia.org/wiki/Base64). In order to access headers and other HTTP properties in .NET (C#) you need to have access to the current Http Context:
HttpContext httpContext = HttpContext.Current;
This you can find in System.Web namespace.
Step 2 - Getting the Header
Authorization header isn't the only only one in the HttpContext. In order to access the header, we need to get it from the request.
string authHeader = this.httpContext.Request.Headers["Authorization"];
(Alternatively you may use AuthenticationHeaderValue.TryParse as suggested in pasx’s answer below)
If you debug your code you will see that the content of that header looks similar to this:
Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Step 3 - Checking the header
You've already extracted the header now there are several things you need to do:
Check that the header isn't null
Check that the Authorization/Authentication mechanism is indeed "Basic"
Like so:
if (authHeader != null && authHeader.StartsWith("Basic")) {
//Extract credentials
} else {
//Handle what happens if that isn't the case
throw new Exception("The authorization header is either empty or isn't Basic.");
}
Now you have check that you are have something to extract data from.
Step 4 - Extracting credentials
Removing "Basic " Substring
You can now attempt to get the values for username and password. Firstly you need to get rid of the "Basic " substring. You can do it like so:
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
See the following links for further details:
http://msdn.microsoft.com/en-us/library/system.string.substring(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/t97s7bs3(v=vs.110).aspx
Decoding Base64
Now we need to decode back from Base64 to string:
//the coding should be iso or you could use ASCII and UTF-8 decoder
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
Now username and password will be in this format:
username:password
Splitting Username:Password
In order to get username and password we can simply get the index of the ":"
int seperatorIndex = usernamePassword.IndexOf(':');
username = usernamePassword.Substring(0, seperatorIndex);
password = usernamePassword.Substring(seperatorIndex + 1);
Now you can use these data for testing.
The Final Code
The final code may look like this:
HttpContext httpContext = HttpContext.Current;
string authHeader = this.httpContext.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic")) {
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
int seperatorIndex = usernamePassword.IndexOf(':');
var username = usernamePassword.Substring(0, seperatorIndex);
var password = usernamePassword.Substring(seperatorIndex + 1);
} else {
//Handle what happens if that isn't the case
throw new Exception("The authorization header is either empty or isn't Basic.");
}
Just adding to the main answer, the best way to get rid of the "Basic" substring is to use AuthenticationHeaderValue Class:
var header = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
var credentials = header.Parameter;
It will throw a FormatException if the content of the header is not valid, e.g.: the "Basic" part is not present.
Alternatively if you do not want to have exception, use AuthenticationHeaderValue.TryParse
Awesome answer from #DawidO.
If you are just looking to extract the basic auth creds and rely on the .NET magic given you have HttpContext, this will also work:
public static void StartListener() {
using (var hl = new HttpListener()) {
hl.Prefixes.Add("http://+:8008/");
hl.AuthenticationSchemes = AuthenticationSchemes.Basic;
hl.Start();
Console.WriteLine("Listening...");
while (true) {
var hlc = hl.GetContext();
var hlbi = (HttpListenerBasicIdentity)hlc.User.Identity;
Console.WriteLine(hlbi.Name);
Console.WriteLine(hlbi.Password);
//TODO: validater user
//TODO: take action
}
}
}
Remember, using strings can be less secure. They will remain in memory untill they are picked by GC.
I've been developing an internal ASP.NET web forms application for our business and one of the requirements is to display our Twitter feed on our portal home page to all users.
For this I've decided that it is best to use LinqToTwitter Single User Authorisation to get the statuses for everyone without them having to authenticate their own accounts.
My main problem at the minute is that when we use the auth object to get the TwitterContext, it returns with an error on the TwitterContext saying
Value cannot be null
on every internal context object.
I've gone through our twitter application settings at http://dev.twitter.com and I have our correct consumer key/token and access key/token. The permission for the application is set to Read-Only. There is no callback URL specified on the http://dev.twitter.com website as it is currently on our internal system (so it wouldn't be able to get back anyway). Is this where it is going wrong? Do I need to forward some ports and allow the callback to get through to our development machines?
Here's the code for prudence. As far as I can see, there is nothing wrong with it. I know that it is set to .FirstOrDefault, this was just for seeing whether it is actually getting anything (which it isn't).
Thanks for any help you can give! :)
private async Task GetTweets()
{
var auth = new SingleUserAuthorizer
{
CredentialStore = new SingleUserInMemoryCredentialStore
{
ConsumerKey = ConfigurationManager.AppSettings["consumerKey"],
ConsumerSecret = ConfigurationManager.AppSettings["consumerSecret"],
AccessToken = ConfigurationManager.AppSettings["accessToken"],
AccessTokenSecret = ConfigurationManager.AppSettings["accessTokenSecret"],
}
};
try
{
using (TwitterContext twitterContext = new TwitterContext(auth))
{
var searchResponse = await (from c in twitterContext.Status
where c.Type == StatusType.User
&& c.ScreenName == "my_screenname"
select c).ToListAsync();
Tb_home_news.Text = searchResponse.FirstOrDefault().Text;
}
}
catch (Exception ex)
{
Tb_home_news.Text = ex.Message;
}
}
If you're creating a Web app, you do need to add a URL to your Twitter App page. It isn't used for the callback, but might help avoid 401's in the future if you're using AspNetAuthorizer.
It looks like you have a NullReferenceException somewhere. What does ex.ToString() say?
Double check CredentialStore after initialization to make sure that all 4 credentials are populated. AccessToken and AccessTokenSecret come from your Twitter app page.
Does searchResponse contain any values? Calling FirstOrDefault on an empty collection will return null.
I have some code on my C# webservice, that checks the header string contains a valid user.
The code is:
MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
String soapHeader = headers.GetHeader<String>("VerifyUser", "http://companyname.co.uk");
Where soapHeader is the string I check. (currently contains username and password(MD5))
How would I send a string from SAVON Rails in the header, so that it can be pulled back off on the webservice.
Preferably without changing the current C# code, unless you can specify a way of sending from a C# client as well.
Ive tried
response = client.request :wsdl, :get_customer_centre_details do
soap.header = { "VerifyUser" => "1:5F4DCC3B5AA765D61D8327DEB882CF99" }
end
Cheers!
EDIT: This is how I currently add the header in C#
OperationContextScope scope = new OperationContextScope(ConChannel);
MessageHeader<String> header = new MessageHeader<String>(UserID + ":" + md5HashString);
var untyped = header.GetUntypedHeader("VerifyUser", "http://www.companyname.co.uk");
OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
What I was missing was the attributes option, to add on the XML namespace, hence it was not being identified as the same header.
response = client.request :wsdl, :get_services do
soap.header = { "VerifyUser" => "1:5F4DCC3B5AA765D61D8327DEB882CF99", :attributes! => { "VerifyUser" => { "xmlns" => "http://www.companyname.co.uk"} } }
end