Retrieve Access Token from IdentityServer - token

I need to get hold of the access token in the Login action of my AccountController of IdentityServer web app.
I need this access token in this action method so that I can log some audit related information to a table in the database.
I am not able to find out how I can get hold of this access token.
I have the following:
var tokenClient = new TokenClient("https://www.example.com/Identity/connect/token", "my.web", new Secret("secret".Sha256()).ToString());
var response = await tokenClient.RequestAuthorizationCodeAsync("code", "https://www.example.com/myweb/callback.html");
var token = response.AccessToken;
The value for the token is always coming as NULL. I am not sure what value I should pass for the "code". From where can I retrieve this value.
Kindly share some detailed example of how I can retrieve the access token.

Related

Where can I store an access token object to be available in the application in rails

I am retrieving an access_token object in order to authenticate my application.
qb_access_token = quickbooks_credentials.access_token
qb_refresh_token = quickbooks_credentials.refresh_token
access_token = OAuth2::AccessToken.new(oauth2_client, qb_access_token, refresh_token: qb_refresh_token)
Where is the right place to store this information and have it available in controllers and models?

How do I get User Profile Data from Janrain in Rails

How can I store values of a registration form which are going to Janrain database through Janrain capture authentication in my local postgresql database. My application is in RoR.
Firstly, you shouldn't need to store registration form data in your own database. That would be redundant when using Janrain Registration.
Once the user is authenticated and the Janrain OAuth token has been sent to the Registration widget you can use that token to call the entity endpoint:
https://SOME_APP_NAME.janraincapture.com/entity?access_token=someaccesstoken
This will return the authenticated user's profile data in json format. You can filter out fields using the attributes parameter as documented here: https://docs.janrain.com/api/registration/entity/
https://SOME_APP_NAME.janraincapture.com/entity?access_token=someaccesstoken&attributes='["uuid","familyName","givenName"]'
You should probably bind to the Janrain Registrations Javascript event handler: "onCaptureCreateSession" which when fired will contain the access token. You can then send that token to your server where it can make the entity api call and then store any relevant data in your server (if necessary).
janrain.events.onCaptureSessionCreated.addHandler(function(result) {
//make an ajax call to your server here with the token:
var token = result.accessToken
});
If you absolutely must get form field data before the form is submitted you could bind to the form's onSubmit event and simply retrieve the field data from the form before it is submitted. This should be achievable using plain Javascript or most mainstream libraries.
Here's an example that should get you started:
janrain.events.onCaptureRenderComplete.addHandler(function(result) {
if (result.renderingBuiltInScreen == false) {
//NOTE: screen names can be configuration dependent.
if(result.screen == "traditionalRegistration" || result.screen == "socialRegistration"){
//bind to rendered form here and do stuff
//form names and field names are configuration dependent.
}
}
}

how to get isAuthenticated working in client mvc app ,in cross platform authentication and autherization(web api)

I am using mvc application and web api 2 with asp.net identity 2.
my client mvc application working with tokens,
it gives an api call on login submit button then web api service returns
a token and user claim (i.e username)
my question are following:
how to use IsAuthenticated property in my mvc app as its always
false.
how to give a remember me feature to my uses.
Is it necessary that my api would return userclaim-username and accesstoken and other data, can I get email and phone as user claims.
Update:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var responseDictionary = GetResponseAsDictionary(model.usename, model.password);
return View(model);
}
I am getting this response dictionary from web api
Now how can I set IsAuthenticated by using this token from service?
I know how to do this in forms authentication but I have no idea how to do this using AccessTokens,
and I would also like to persist this token across the user session in tempData or session.
it was easy to do , i can use
`
formsAuthentication.SetAuthCookie
` on Client app and i had to redirect the page after setting this cookie
1: Get the Authtoken from web api
2: if it returns Access_token ,then you can set authcookie
3: finnaly you can use IsAuthenticated property on client App
4: i would ask another question for how to do a remember me feature
,as i dont know how to store token and is
it safe to store as it is without further encripting it.

how to verify referrer inside a MVC or Web Api ajax call

my MVC app has common ajax methods (in web api and regular controller). I'd like to authorize these calls based on which area (view) of my app the call is coming from. The problem I am facing is how to verify the origin of the ajax call.
I realize that this is not easily possible since ajax calls are easy to spoof, but since I have full control of how the view gets rendered (full page source) perhaps there is a way to embed anti-forgery type tokens that could later be verified to a Url Referrer.
Authentication is already handled and I can safely verify the identity of the call, the only problem is verifying which URL (MVC route) the call came from. More specifically, preventing the user from being able to spoof the origin of the ajax call.
I tried creating a custom authorization header and passing it between view render and ajax calls, and that works, but still easy to spoof (since a user could sniff the headers from another part of the site and re-use those). In the end I am not sure how to safely verify that the header has not been spoofed. The only thing that comes to mind is encoding some info about the original context inside the token, and validating it somehow against incoming call context (the one that's passing the token in ajax call).
I see that MVC has AntiForgery token capabilities, but I am not sure if that can solve my problem. If so I'd like to know how it could be used to verify that /api/common/update was called from /home/index vs /user/setup (both of these calls are valid).
Again, i'd like a way to verify which page an ajax call is coming from, and user identity is not the issue.
update
as per #Sarathy recommended I tried implementing anti-forgery token. As far as I can tell this works by adding a hidden field with token on each page, and comparing it to a token set in a cookie. Here is my implementation of custom action filter attribute that does token validation:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var req = filterContext.RequestContext.HttpContext.Request;
var fToken = req.Headers["X-Request-Verification-Token"];
var cookie = req.Cookies[AntiForgeryConfig.CookieName];
var cToken = cookie != null
? cookie.Value
: "null";
log.Info("filter \ntoken:{0} \ncookie:{1}", fToken, cToken);
AntiForgery.Validate(cToken, fToken);
base.OnActionExecuting(filterContext);
}
then my anti forgery additional data provider looks like this:
public class MyAntiForgeryProvider : IAntiForgeryAdditionalDataProvider
{
public string GetAdditionalData(System.Web.HttpContextBase context)
{
var ad = string.Format("{0}-{1}",context.Request.Url, new Random().Next(9999));
log.Info("antiforgery AntiForgeryProvider.GetAdditionalData Request.AdditionalData: {0}", ad);
log.Info("antiforgery AntiForgeryProvider.GetAdditionalData Request.UrlReferrer: {0}", context.Request.UrlReferrer);
return ad;
}
public bool ValidateAdditionalData(System.Web.HttpContextBase context, string additionalData)
{
log.Info("antiforgery AntiForgeryProvider.ValidateAdditionalData Request.Url: {0}", context.Request.Url);
log.Info("antiforgery AntiForgeryProvider.ValidateAdditionalData additionalData: {0}", additionalData);
return true;
}
this works, in that i can see correct pages logged in the provider, and anti forgery breaks w/out the tokens.
however, unless i did something wrong, this seems trivial to spoof. for example
if i go to pageA and copy the token form pageB (just the form token, not even the cookie token), this still succeeds, and in my logs i see pageB while executing ajax method from pageA
confirmed that this is pretty easy to spoof.
I am using csrf to generate ajax tokens like this:
public static string MyForgeryToken(this HtmlHelper htmlHelper)
{
var c = htmlHelper.ViewContext.RequestContext.HttpContext.Request.Cookies[AntiForgeryConfig.CookieName];
string cookieToken, formToken;
AntiForgery.GetTokens(c != null ? c.Value : null, out cookieToken, out formToken);
return formToken;
}
I then pass the form token back with each ajax call and have a custom actionfilterattribute where I read/validate it along with cookie token
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var req = filterContext.RequestContext.HttpContext.Request;
var fToken = req.Headers[GlobalConstants.AntiForgeKey];
var cookie = req.Cookies[AntiForgeryConfig.CookieName];
var cToken = cookie != null
? cookie.Value
: "null";
log.Info("MyAntiForgeryAttribute.OnActionExecuting. \ntoken:{0} \ncookie:{1}", fToken, cToken);
AntiForgery.Validate(cToken, fToken);
this all works (changing anything about the token throws correct exception), then in my IAntiForgeryAdditionalDataProvider I can see what it thinks it's processing.
as soon as i override the csrf token from another view, it thinks it's that view. I don't even have to tamper with the UrlReferrer to break this :/
one way this could work if i could force the cookie to be different on every page load
I am assuming you can use IAntiForgeryAdditionalDataProvider for this.
public class CustomDataProvider : IAntiForgeryAdditionalDataProvider
{
public string GetAdditionalData(HttpContextBase context)
{
// Return the current request url or build a route or create a hash from a set of items from the current context.
return context.Request.Url.ToString();
}
public bool ValidateAdditionalData(HttpContextBase context, string additionalData)
{
// Check whether the allowed list contains additional data or delegate the validation to a separate component.
return false;
}
}
Register the provider in App_Start like below.
AntiForgeryConfig.AdditionalDataProvider = new CustomDataProvider();
https://msdn.microsoft.com/en-us/library/system.web.helpers.iantiforgeryadditionaldataprovider(v=vs.111).aspx
Hope this helps in your scenario.
You mentioned in your question that you're looking for Anti-forgery token capabilities.
Hence, I think what you're asking about is an anti-CSRF solution (CSRF=cross site request forgery).
One way to do this is to render a true random number (a one-time token) into your page, then passing it on each request, which can be done by adding a key/value pair to the request header and then checked at the backend (i.e. inside your controller). This is a challenge-response approach.
As you mentioned, in the server-side code you can use
var fToken = req.Headers["X-Request-Verification-Token"];
to get it from the requesting page.
To pass it along from each client AJAX request of the page, you can use
var tokenValue = '6427083747'; // replace this by rendered random token
$(document).ajaxSend(function (event, jqxhr, settings) {
jqxhr.setRequestHeader('X-Request-Verification-Token', tokenValue);
});
or you can set it for each request by using
var tokenValue = '2347893735'; // replace this by rendered random token
$.ajax({
url: 'foo/bar',
headers: { 'X-Request-Verification-Token': tokenValue }
});
Note that tokenValue needs to contain the random number which was rendered by the web server when the web page was sent to the client.
I would not use cookies for this, because cookies don't protect you against CSRF - you need to ensure that the page, which is requesting is the same as the page which was rendered (and hence created by the web server). A page being on a different tab in the same browser window could use the cookie as well.
Details can be found on the OWASP project page, in the OWASP CSRF prevention cheat sheet.
My quick interim solution was to use custom tokens created on each page load (guid which i keep track of in my token cache), which are passed as headers in all ajax calls. Additionally i create a original url hash and combine it into the custom auth token.
in my ajax methods I then extract the hash and compare it with UrlReferrer hash to ensure that hasn't been tampered with.
since the custom token is always different it's less obvious to guess what's going on as token appears to be different on every page load. however this is not secure because with enough effort the url hash can be uncovered. The exposure is somewhat limited because user identity is not the problem so worst case is a given user would gain write access to another section of the site but only as himself. My site is internal and i am auditing every move so any temper attempts would be caught quickly.
I am using both jQuery and angular so appending tokens with all requests like this:
var __key = '#Html.GetHeaderKey()' //helper method to get key from http header
//jQuery
$.ajaxSetup({
beforeSend: function (xhr, settings) {
xhr.setRequestHeader('X-Nothing-To-See-Here', __key); // totally inconspicuous
})
//angular
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common['X-Nothing-To-See-Here'] = __key;
});
update
the downside of this approach is that custom tokens need to be persisted across a web farm or app restarts. Based on #Sarathy's idea I am trying to side step this by leveraging MVC anti forgery framework. Basically add/remove my "salt" and let the framework manage the actual token validation. That way it's a bit less to manage for me. Will post more details once i verify that this is working.
So this is going to be one of those "you're doing it wrong" answers that I don't like, and so I apologize up front. In any case, from the question and comments, I'm going to propose you approach the problem differently. Instead of thinking about where did the request come from, think about what is the request trying to do. You need to determine if the user can do that.
My guess as to why this is hard in your case is I think you have made your api interface too generic. From your example api "api/common/update" I'm guessing you have a generic update api that can update anything, and you want to protect updating data X from a page that is only supposed to access data Y. If I'm off base there then ignore me. :)
So my answer would be: don't do that. Change your api around so it starts with the data you want to work with: api/dataX api/dataY. Then use user roles to protect those api methods appropriately. Behind the scenes you can still have a common update routine if you like that and it works for you, but keep the api interface more concrete.
If you really don't want to have an api for each table, and if its appropriate for you situation, perhaps you can at least have an api for protected/admin tables and a separate api for the standard tables. A lot of "if"s, but maybe this would work for your situation.
In addition, if your user can update some dataX but not other dataX, then you will have to do some sort of checking against your data, ideally against some root object and whether your user is authorized to see/use that root object.
So to summarize, avoid an overly generic api interface. By being more concrete you can use the existing security tools to help you.
And good luck!

OWIN social facebook provider will not list public profile

I making a facebook login using the new setup in ASPNET mvc 5. When the user login I can see that there is a request for the default public profile, but all I'm getting back is the token, username and nothing else.
I thought that by default I would also get information like first and lastname. And if added to the scope also the email.
On the callback from facebook I'm having this code to extract the information:
var authManager = HttpContext.GetOwinContext().Authentication;
var loginInfo = await authManager.GetExternalLoginInfoAsync();
Thanks to the comment, I was able to find out that I needed to look into the identity of the callback to get the requested information
var loginIdentity = await authManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
This will provide everything beside the logintoken/provider.
I needed to look at the ExternalIdentity and not the ExternalLoginInfo. The post is updated with this info. Also important to add email to the scope

Resources