Sign out a user OneDrive API - c#

I want to sign out a user in OneDrive API, I tried this, I sent the request:
var client = new RestClient("https://login.live.com/oauth20_logout.srf?client_id=762d0c10-xxxx-xxxx-xxxx-085a4a1743bc&redirect_uri=urn:ietf:wg:oauth:2.0:oob");
var request = new RestRequest(Method.GET);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
IRestResponse response = client.Execute(request);
Console.WriteLine((int)response.StatusCode);
Console.WriteLine(response.IsSuccessful);
output:
302
False
my question is how to send a logout request

OAuth is inherently stateless so there is really nothing to "sign out" of. When you complete the OAuth flow you receive a token back. That token is used to authenticate the user every time you call the API. If you don't include the token in the Authorization header, the API will reject your request.
So to "sign out", simply wipe any stored access token values from your app's memory/storage and the app will no longer have access to that user's account.

I am afraid you did not follow the rules before performing the request:
Delete any cached access_token or refresh_token values you've
previously received from the OAuth flow.
Perform any sign out actions in your application (for example,
cleaning up local state, removing any cached items, etc.).
Only after can you make a call to the authorization web service using the url:
https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri={redirect-uri}
After removing the cookie, the browser will be redirected to the redirect URL you provided. When the browser loads your redirect page, no authentication query string parameters will be set, and you can infer the user has been logged out.

Related

Protect URL from different user browser

Application built in: React and .NET web api
Process:
I have created GET Api in backend for download image from azure blob. In the request, User[Frontend] pass (login)auth token and Image URL to backend as queary string. After validation of auth token backend return binary data to app.
Sample URL: https://***:4412/file/downlaodFile?filePath=~/Uploads/Images/576659969_911903629_flower-color-400x391.jpg&authToken=da72e5bc0d35d692a4c85e8442366713fc9494c8cf56aa1f326560d06a24db5c16e562b82ad5f86e74d8e417c9695007922c9678c91ea234fa7675164eeb041b
Problem: After login if user copy that URL and send it to other people so they can also download Image because Auth token is valid for 15 mins.
How can I protect that URL..?
Thnaks!!
You want to put the auth token in the headers of the request; never ever put the auth token in the url for security concerns.
More information about the Authorization header can be found here https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization

How can I get an OAuth2 bearer token from the browser?

I'm trying to get a bearer authentication token from a browser web page.
I'm using selenium and previously I could login to our URL and the bearer token was displayed in a form field. Now it has changed and the token is hidden. How can I extract that token and store into a variable?
This was my previous code (i know it's not great but I am not a developer by any means)..
IWebElement tokenField = getDriver().FindElement(By.XPath("/html/body/div[2]/div[2]/div[2]"));
string token = tokenField.Text;
restClient.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(token, "Bearer");
request.AddHeader("Accept", "application/json");
Any help would be appreciated. I am very new to OAuth2 and just security in general.
Usually you won't be able to find sensitive data like auth token displayed in the FE.
If the token is hidden and you cannot take it from FE or DOM, you can login using API calls and from there to get the token which can be used in the further requests.
If you're working within a development team, you can ask a dev to guide you with this and provide login url and other necessary stuff.

"invalid_grant" error from DocuSign token api from an Angular SPA

I'm using the below code to get access token and refresh token from docusign.
But I'm always getting the invalid-grant error. I'm pasting the code below.
[HttpGet("GetDocToken")]
[AllowAnonymous]
public async Task<IActionResult> getToken(string docCode)
{
var x = docCode.Length;
var client = new HttpClient();
var authCode=Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("ced8998a-4387-4f30-9ab7-51c0d1af49bf:d7c3ccd4-22fa-4f18-a540-ddf11d8b2c9f"));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authCode);
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var requestContent = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", docCode),
new KeyValuePair<string, string>("redirect_uri", "http://localhost:4200/auth")
});
HttpResponseMessage response = await client.PostAsync("https://account-d.docusign.com/oauth/token", requestContent);
string resultContent = response.Content.ReadAsStringAsync().Result;
return Ok(response.Content.ReadAsStringAsync());
}
My assumption is that you have received the authentication code back from the DocuSign identity system and are trying to exchange it for an access token.
A couple of issues:
The docs incorrectly indicates that the redirect_uri should be included in the request. The Example Request in the docs does correctly show that the request should only include the grant_type and code parameters.
Note: While the OAuth standard, section 4.1 (d) does indicate that the redirect_url should be included, DocuSign usually does not include it.
My guess is that DocuSign will ignore the redirect_uri parameter, but you might want to try leaving it out.
Another issue is timing: The authorization code you receive back from DocuSign is only good for a minute or so. If you're not immediately using the authorization code (your code's docCode) then you'll get the Invalid Grant error.
Known good example software
I suggest that you also check out the known-good code example for C#. You can use a protocol peeker to see exactly what it is doing during the authentication.
Use a library
I also suggest that you look for an OAuth Authorization Code client library that you can use instead of rolling your own.
For example, are you setting and checking the state value? It's important to do that to stop CSRF attacks. See this article.
Added
It is also not clear to me that you are using the right value as the authorization code.
I believe the flow should be:
User presses "Authenticate with DocuSign" in the Angular app.
User's browser does a GET to the DocuSign authentication server. At this point, the browser is no longer running the Angular app.
User's browser and DocuSign Authentication server exchange HTML back and forth as the user authenticates with DocuSign.
The user completes the authentication process with DocuSign.
DocuSign sends a REDIRECT response to the browser, telling the browser to do a GET on the redirect url. The redirect (and the GET) include query parameters for code and state
Your SERVER (not the Angular app), receives the GET request.
Your server should:
Extract the code and state query parameters
Verify that state is the same as was sent in step 2.
Makes the POST request to DocuSign to exchange the authorization code for an access token.
RESPONDS to the browser with the Angular program.
The Angular program is now once again running on the browser.
Use Implicit Grant
Your other option is to use Implicit Grant. That way you don't need a server component. With Implicit Grant, your Angular program handles the flow.

How do I know which cookie(s) are must to make a correct HttpWebRequest?

I am working on a download manager and trying to get cookie required contents using HttpWebRequest. I want to integrate my application to Chrome and so I can get the necessary cookie headers and values from the browser.
But first I need to know if cookie is required to get a content to download and which cookies are they. I can't find any helpful resource about this topic.
This is what I imagine:
HttpWebRequest req = (WebRequest.Create(url)) as HttpWebRequest;
//At first, get if cookies are necessary?
//If it is, get the required cookie headers
//Then add the cookies to the request
CookieContainer cc = new CookieContainer();
Cookie c1 = new Cookie("header1", "value1");
Cookie c2 = new Cookie("header2", "value2");
CookieCollection ccollection = new CookieCollection();
ccollection.Add(c1);
ccollection.Add(c2);
cc.Add(uri, ccollection);
req.CookieContainer = cc;
//Get response and other stuff......
How can I do these steps?
The cookies required to get content from a server are specified by that server in the HTTP response's "Set-Cookie" header. The generic scenario is:
Client makes an HTTP request to the server (this could be a login page, or a download page)
Server responds with HTTP response that contains "Set-Cookie" header(s)
Client remembers all those cookies
Client uses the cookies stored in step 3 for all subsequent requests to the same server
Now, considering your scenario of integrating into Chrome, I imagine that the initial requests (steps 1 to 3) will not be done by your application, but by the Chrome itself. The cookies will be stored in the Chrome's cookie store. So what your application will need to do is to get from Chrome all cookies for the domain where you want to download from, and include those cookies in your request (step 4).
See chrome.cookies document on how to use Chrome API to interact with its cookie store, and Set-Cookie docs from Mozilla for the in-depth description of how cookies are specified in the HTTP response.
Try to capture the cookies from first request (a login page may be) and add all those in next request (download request). Something like below.
public void MakeRequest()
{
var container = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://example.com/loginpage");
request.Method = WebRequestMethods.Http.Get;
request.CookieContainer = container;
HttpWebResponse response = null;
response = (HttpWebResponse)request.GetResponse();
//once you read response u need to add all cookie sent in header to the 'container' so that it can be forwarded on second response
foreach (Cookie cookie in response.Cookies)
{
container.Add(cookie);
}
HttpWebRequest downRequest = (HttpWebRequest)WebRequest.Create("http://example.com/downloadpage");
downRequest.Method = WebRequestMethods.Http.Get;
downRequest.Proxy = null;
//As you have added the cookies, this must response fine now
downRequest.CookieContainer = container;
response = (HttpWebResponse)downRequest.GetResponse();
var stream = response.GetResponseStream();
}
Hope this helps.
You definitely should integrate cookie because web sites requiring to identify user set data into cookie
without that token you can't perform the download
Cookie to be used are site dependent, you can't guess if the web site needs them or not, which are needed or not
If you are using .Net 4.5+, consider using "WebRequest.CreateHttp" static method
https://msdn.microsoft.com/fr-fr/library/ff382788(v=vs.110).aspx
Keep track of the CookieContainer, it will eventually be populated with new cookie from response (Set-Cookie header in response)
note : cookie are linked to a domain (ie stackoverflow.com)
I suggest you install a cookie extension to your Chrome browser to play with
This depends on actual download you want to perform and requirements of the server. Most servers will allow download regardless of cookies.
However, you can always send cookies just in case. What cookies you need? Here are some rules how browsers do it:
Cookie have Domain and Path attributes. Domain applies to subdomains.
So, if request is made for http://foo.bar.com/some/path following cookies will be sent:
-Those with domain com, bar.com and foo.bar.com without path
-Same as previous but having paths like /some or some/path etc.
It will not send cookies from other domains nor from domains listed above but with path not contained in path of request.
So, you would have to search for cookies in same way depending on URL of file you should download.
I would have added a comment instead, but don't have enough rep. You seem to be on the right track. Mateusz Radny's suggestion to use EditThisCookie will allow you to explore cookies you have in your browser, but for any particular web server you don't usually* need to decide which cookie is which (so you really don't need to care which is the login cookie).
The protocol for cookies is that the browser should send back the cookies that the web server initially sent to the browser for that particular website. Might help to read a bit more about cookies: https://en.wikipedia.org/wiki/HTTP_cookie (probably jump to Implementation, and then read up a bit in Privacy and third-party cookies because you really don't want to sharing cookies from one website with other websites).
So assuming you want to emulate what the browser would send, make sure your download manager also sends the same set of cookies that Chrome received from that particular website and it should work. Also avoid caching the cookies in your code, since your browser will update the cookies (e.g. delete expired cookies) and so you should always get them from the browser each time you need it.
*Note: Sometimes a cookie is marked for certain types of connections only or for use with a particular domain/sub-domain or Uri path. If set, then you should limit when you send those back based on if it matches the connection you're trying to make. Please research this separately (latest RFC specs: https://www.rfc-editor.org/rfc/rfc6265).
PS: The web server may send back new or updated cookies as part of the download request you made via your download manager. If you really want to be perfect, these should be copied from your download manager back to Chrome's cookie set (though I'm not familiar with the Chrome API so not sure how hard that would be).

Session lost after first Twitter OAuth request

Using ASP.NET MVC, sessions are stored in SQL database (never had a problem with them, and didn't use web farm). Using also Twitterizer2 library. Using Firefox.
First request, no browser instances is opened. Browser instance is started.
We have simple form "Publish on twitter" and submit button Share.
When Share is clicked we store message in Session and redirect to Twitter's OAuth authentication (on POST submit).
We authenticate OK and return to our Action and before posting to Twitter we check if message is stored in Session (and it isn't! - it is lost immediately after Twitter redirection)
When we try another messsage Share it is now working (Session).
We solved it using a Cookie but we don't have a clue while we lost Session (first time) after returning from Twitter.
Any deas?
I'd like to ask how did you maintained the session without cookie the first time?
I think the problem can be of the cookie set process. I also experienced similar problem before a couple of weeks.
The problem was that when I make request for REQUEST token, this request is internal HTTP request (not via user browser). As a response to this request I get REQUEST token and then set it in the user session.
$token = getRequestToken();
$_SESSION['token'] = $token;
However, if the user just came to my site for first time without a session, he does not have a session cookie to sent me. Internally at the web site I have created a session for him, and stored the token inside it, but then instead of sending him response with cookie headers included, so that he "accepts" my session, I make redirect to the provider authorize endpoint. This way, the user does not get the session cookie, and when he is returned back, he is like a new user for my site.
This is the flow of the process that happened to me:
create user session in the database
setcookie(usersession) // add headers to the eventual response
get request token
set the token in the session
redirect the user (user does not receive the session cookie)
user goes to authorization point
user returns, but he is a new user for me
I'd be interested to know if you had similar problem :)
Best regards
check the request and callback domain are the same
i.e. you are making request for oauth from localhost and callback to 127.0.0.1

Categories