Sharing session between two web applications on the same IIS server - c#

I have a web application developed in MVC 2.0. I have created a dynamic data website for this web application. For accessing the dynamic data website, the user is redirected to the login page of the MVC application.
On login, the session is created for the user. I want to access this session on my dynamic data website for checking the user's role and username. If the user has the admin role, then only user is allow to access the dynamic data website.
How can I achieve this?

Try this solution:
On your First Web App (The one that user is used for login)
//create a method that will redirect to your web app 2
public ActionResult RedirectToAnotherSite(string name, string role)
{
//specify the IP or url for your web app 2
//pass the parameters
var rawUrl = string.Format("http://localhost:8051?name={0}&role={1}", name, role);
return Redirect(rawUrl);
}
On your web app 2 (dynamic) open the file Global.asax and add the following code
void Application_BeginRequest(object sender, EventArgs e)
{
//get the passed parameters
var req = ((HttpApplication)(sender)).Request;
var name = req.QueryString["name"] ?? string.Empty;
var role = req.QueryString["role"] ?? string.Empty;
//check the role
if (!role.Equals("admin"))
{
//return http access denied
var res = ((HttpApplication)(sender)).Response;
res.StatusCode = 401;
}
}

Related

Running all SSRS reports through one report user ignoring own users domain

I have the following code which returns the reports from my SSRS server, afterwards I then store the paths to each individual list which allows users to run them from within the application. The below works fine.
NetworkCredential serviceCredentials = new NetworkCredential()
{
UserName = username,
SecurePassword = EncryptionManager.DecryptToSecureString(password),
Domain = domain
};
reports = new ObservableCollection<object>(reportsManager.FindReports(reportsWebService, reportsFolderName, serviceCredentials));
//FindReports
ReportingService2005 rs = new ReportingService2005();
rs.Url = reportsWebService;
rs.Credentials = serviceCredentials;
CatalogItem[] catalogItems = rs.ListChildren(#"/" + reportsFolderName, false);
However the problem is when a user selects a report to view it shows the following error:
The permissions granted to user are insufficient for performing this
operation.
I understand that the quick fix to this would be to add the users domain into the security section on the Report server, however this is not appropriate.
My question is I can supply credentials to allows a specified user to access the report folder is it possible to pass this along so that user can run a report?
Each of my reports use built in connection strings NOT windows authentication.
Edit: I am using Reporting WinForms.
Windows Forms
In a windows forms project you can pass a suitable System.Net.NetworkCredential to ServerReport.ReportServerCredentials.NetworkCredentials property of ReportViewer. This way, all reports will be executed using the passed credential:
reportViewer1.ServerReport.ReportServerCredentials.NetworkCredentials =
new System.Net.NetworkCredential("username", "password", "domain");
Web Forms
The solution for a Web Forms is different. In a Web Forms project, to pass a suitable credential to RePortViewer you need to implement IReportServerCredentials. Then you can assign the value to ServerReport.ReportServerCredentials property of ReportViewer control. This way, all reports will be executed using the passed credential.
Example
Here is a simple implementation. It's better to store username, password and domain name in app config and read them from config file:
using System;
using System.Net;
using System.Security.Principal;
using Microsoft.Reporting.WebForms;
[Serializable]
public sealed class MyReportServerCredentials : IReportServerCredentials
{
public WindowsIdentity ImpersonationUser { get { return null; } }
public ICredentials NetworkCredentials
{
get
{
return new NetworkCredential("username", "password", "domain");
}
}
public bool GetFormsCredentials(out Cookie authCookie, out string userName,
out string password, out string authority)
{
authCookie = null;
userName = password = authority = null;
return false;
}
}
Then in Page_Load pass the credential this way:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
this.ReportViewer1.ServerReport.ReportServerCredentials =
new Sample.MyReportServerCredentials();
}
Note
In cases which you want to use ReportViewer with no session state you can also implement IReportServerConnection. In this case you need to add a key value in appsettings section of config file to introduce the implementation this way:
<add key="ReportViewerServerConnection" value="YourNameSpace.YourClass, YourAssemply" />
In this case, you don't need code in Page_Load and the config would be enough. For more information take a look at this great blog post by Brian Hartman.

Login with twitter to get user profile asp.net

I have a web application in asp.net . I want to use login with twiiter to get get user info. I have followed all instructions mentioned in below article
http://www.aspsnippets.com/Articles/Login-with-Twitter-in-ASPNet-using-Twitter-Button.aspx
I am getting redirected to twitter app then after authentication I am being redirected to my localhost app. Then I have check user is authorized but when I try to get user details by method FetchProfile() I am getting error.
My code is as below :
First on button click
protected void LoginTwitter(object sender, EventArgs e)
{
if (!TwitterConnect.IsAuthorized)
{
TwitterConnect twitter = new TwitterConnect();
twitter.Authorize(Request.Url.AbsoluteUri.Split('?')[0]);
}
}
then after authenticating back from twitter . on page load of application
I have check url its
http://localhost:63977/Account/Login?oauth_token=K0mECAAAAAAAxRXEAAABV44xPgc&oauth_verifier=qYLFiOlFPx4gxEu6V4AmTJG2JNjJ3nV2
then code to check
protected void Page_Load(object sender, EventArgs e)
{
TwitterConnect.API_Key = HelperClasses.TwitterApiKey;
TwitterConnect.API_Secret = HelperClasses.TwitterApiSecret;
if (Request.QueryString["oauth_token"] != null)
{
//twiiter
if (TwitterConnect.IsAuthorized)
{
TwitterConnect twitter = new TwitterConnect();
//LoggedIn User Twitter Profile Details
DataTable twitterUserDataTable = twitter.FetchProfile(); // error here
}
}
}
Tweetinvi provides a sample project doing exactly what you want to do : https://github.com/linvi/tweetinvi/tree/master/Examplinvi.Web.
I have highlighted the lines you will be interested in :
https://github.com/linvi/tweetinvi/blob/master/Examplinvi.Web/Controllers/HomeController.cs#L14-L36
You can also find more about the Authentication in tweetinvi here : https://github.com/linvi/tweetinvi/wiki/Authentication.
Here is the snippet that you want to use of ASP.NET authentication :
private IAuthenticationContext _authenticationContext;
// Step 1 : Redirect user to go on Twitter.com to authenticate
public ActionResult TwitterAuth()
{
var appCreds = new ConsumerCredentials("CONSUMER_KEY", "CONSUMER_SECRET");
// Specify the url you want the user to be redirected to
var redirectURL = "http://" + Request.Url.Authority + "/Home/ValidateTwitterAuth";
_authenticationContext = AuthFlow.InitAuthentication(appCreds, redirectURL);
return new RedirectResult(authenticationContext.AuthorizationURL);
}
public ActionResult ValidateTwitterAuth()
{
// Get some information back from the URL
var verifierCode = Request.Params.Get("oauth_verifier");
// Create the user credentials
var userCreds = AuthFlow.CreateCredentialsFromVerifierCode(verifierCode, _authenticationContext);
// Do whatever you want with the user now!
ViewBag.User = Tweetinvi.User.GetAuthenticatedUser(userCreds);
return View();
}

Implementing External Authentication for Mobile App in ASP.NET WebApi 2

I'm trying to build an API (using ASP.NET WebApi) that will be consumed by a native mobile app for a school project. (I'm not concerned about/developing the mobile app, this responsibility falls on a different member)
I'm at a point where I need to implement a token based Facebook login. There are a lot of tutorials available for how to implement this feature for browser based apps (this is pretty straight forward and most of it comes inbuilt), but I don't think I follow how this would work with native apps. What I don't understand is how the redirects would work?
According to this link, nothing needs to be handled specifically by my server. And I don't think I understand how this would work? How would the tokens from Facebook be handled?
Also, what part of token handling should I implement, I couldn't really find good documentation for WebApi external login authentication.
Anyway, if someone could point me to the exact flow of token exchanges that happen and what is implemented by default by ASP.NET, that would be super helpful.
Also, the biggest point of confusion for me is I don't understand how the token returned by Facebook will be handled.
I assume the token will be returned to the client (mobile app), how do I get access to it on my server?
How do I create a local token from facebook's token?
Is this all done internally/auto-magically by ASP.NET?
I'm sorry if this is something I should've been able to figure out. I did do quite a bit of research and I found myself drowning in (related & unrelated) information. I don't think I even know how to search for the information I need.
Some links I've read:
Claims And Token Based Authentication (ASP.NET Web API)
Token Based Authentication using ASP.NET Web API 2, Owin, and Identity
ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app
I had to do pretty much the same thing for an application I was working on. I also had a lot of trouble finding information about it. It seemed like everything I found was close to what I needed, but not exactly the solution. I ended up taking bits and pieces from a bunch of different blog posts, articles, etc. and putting them all together to get it to work.
I remember two of the links you posted "Claims and Token Based Authentication" and "ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app" as being ones that had useful information.
I can't give you a comprehensive answer since I don't remember everything I had to do, nor did I even understand everything I was doing at the time, but I can give you the general idea. You are on the right track.
Essentially I ended up using the token granted by Facebook to confirm that they were logged into their Facebook account, created a user based on their Facebook user ID, and granted them my own bearer token that they could use to access my API.
The flow looks something like this:
Client authenticates with Facebook via whatever method (we used oauth.io)
Facebook returns them a token
Client sends token information to the registration endpoint of my WebApi controller
The token is validated using Facebook's Graph API, which returns user info
A user is created in the database via ASP.NET Identity with their Facebook user ID as the key
Client sends token information to the authentication endpoint of my WebApi controller
The token is validated using Facebook's Graph API, which returns user info
The user info is used to look up the user in the database, confirm they have previously registered
ASP.NET Identity is used to generate a new token for that user
That token is returned to the client
Client includes an Authorization header in all future HTTP requests with the new token granted by my service (ex. "Authorization: Bearer TOKEN")
If the WebApi endpoint has the [Authorize] attribute, ASP.NET Identity will automatically validate the bearer token and refuse access if it is not valid
There ended up being a lot of custom code for implementing the OAuth stuff with ASP.NET Identity, and those links you included show you some of that. Hopefully this information will help you a little bit, sorry I couldn't help more.
I followed this article. The flow is basically this
The server has the facebook keys just like with web login
The app asks for available social logins and displays buttons (you can hardcode this I guess)
When a button is pressed the app opens a browser and sets the URL to the one related to the specified social login. The ASP.NET then redirects the browser to facebook/google/whatever with the appropriate Challenge
The user might be logged in or not and might have given permission to your app or not. After he gives the permissions facebook redirects back to the provided callback URL
At that point you can get the external login info from the SignInManager and check if the user already exists and if you should create a new account
Finally a token is generated and the browser is redirected to a URL in which the token is placed. The app gets the token from the URL and closes the browser. Uses the token to proceed with API requests.
Honestly I have no idea if this approach is legit...
The code of the action buttons should redirect to:
public async Task<IEnumerable<ExternalLoginDto>> GetExternalLogins(string returnUrl, bool generateState = false)
{
IEnumerable<AuthenticationScheme> loginProviders = await SignInManager.GetExternalAuthenticationSchemesAsync();
var logins = new List<ExternalLoginDto>();
string state;
if (generateState)
{
const int strengthInBits = 256;
state = RandomOAuthStateGenerator.Generate(strengthInBits);
}
else
{
state = null;
}
foreach (AuthenticationScheme authenticationScheme in loginProviders)
{
var routeValues = new
{
provider = authenticationScheme.Name,
response_type = "token",
client_id = Configuration["Jwt:Issuer"],
redirect_uri = $"{Request.Scheme}//{Request.Host}{returnUrl}",
state = state
};
var login = new ExternalLoginDto
{
Name = authenticationScheme.DisplayName,
Url = Url.RouteUrl("ExternalLogin", routeValues),
State = state
};
logins.Add(login);
}
return logins;
}
The code for the callback action:
[Authorize(AuthenticationSchemes = "Identity.External")]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IActionResult> GetExternalLogin(string provider, string state = null, string client_id = null, string error = null)
{
if (error != null)
{
ThrowBadRequest(error);
}
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider);
}
string providerKey = User.FindFirstValue(ClaimTypes.NameIdentifier);
var externalLoginInfo = new ExternalLoginInfo(User, User.Identity.AuthenticationType, providerKey, User.Identity.AuthenticationType);
if (externalLoginInfo.LoginProvider != provider)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
return new ChallengeResult(provider);
}
var userLoginInfo = new UserLoginInfo(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, externalLoginInfo.ProviderDisplayName);
User user = await UserManager.FindByLoginAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey);
if (client_id != Configuration["Jwt:Issuer"])
{
return Redirect($"/#error=invalid_client_id_{client_id}");
}
if (user != null)
{
return await LoginWithLocalUser(user, state);
}
else
{
string email = null;
string firstName = null;
string lastName = null;
IEnumerable<Claim> claims = externalLoginInfo.Principal.Claims;
if (externalLoginInfo.LoginProvider == "Google")
{
email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
firstName = claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
lastName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;
}
else if (externalLoginInfo.LoginProvider == "Facebook")
{
email = claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
string[] nameParts = claims.First(c => c.Type == ClaimTypes.Name)?.Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
firstName = nameParts?.First();
lastName = nameParts?.Last();
}
//some fallback just in case
firstName ??= externalLoginInfo.Principal.Identity.Name;
lastName ??= externalLoginInfo.Principal.Identity.Name;
user = new User
{
UserName = email,
Email = email,
FirstName = firstName,
LastName = lastName,
EmailConfirmed = true //if the user logs in with Facebook consider the e-mail confirmed
};
IdentityResult userCreationResult = await UserManager.CreateAsync(user);
if (userCreationResult.Succeeded)
{
userCreationResult = await UserManager.AddLoginAsync(user, userLoginInfo);
if (userCreationResult.Succeeded)
{
return await LoginWithLocalUser(user, state);
}
}
string identityErrrors = String.Join(" ", userCreationResult.Errors.Select(ie => ie.Description));
Logger.LogWarning($"Error registering user with external login. Email:{email}, Errors:" + Environment.NewLine + identityErrrors);
return Redirect($"/#error={identityErrrors}");
}
}
private async Task<RedirectResult> LoginWithLocalUser(User user, string state)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
DateTime expirationDate = DateTime.UtcNow.AddDays(365);
string token = user.GenerateJwtToken(Configuration["Jwt:Key"], Configuration["Jwt:Issuer"], expirationDate);
return Redirect($"/#access_token={token}&token_type=bearer&expires_in={(int)(expirationDate - DateTime.UtcNow).TotalSeconds}&state={state}");
}

How can I authenticate against ADFS by passing login info as Request headers?

We have a mobile app that wants to access a view on our ASP.NET MVC4 website. In order to do so, the app needs to authenticate by different means than our ADFS login process. The mobile app makes a request to the service and passes in the username and password as Request headers. In the ASP.NET application global.asax file, we have the following:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string username = HttpContext.Current.Request.Headers[Mobile.Configuration.iPadUsername];
string password = HttpContext.Current.Request.Headers[Mobile.Configuration.iPadPassword];
string acctID = HttpContext.Current.Request.Headers[Mobile.Configuration.iPadAcctStr];
//bypass adfs
if (!string.IsNullOrEmpty(username)
&& !string.IsNullOrEmpty(password)
&& !HttpContext.Current.Request.IsAuthenticated)
{
//web service call to authenticate the user
if (success)
{
var genIden = new GenericIdentity(usrnm);
var genClaim = new GenericPrincipal(genIden, new string[] { });
HttpContext.Current.User = genClaim;
var token = FederatedAuthentication.SessionAuthenticationModule.CreateSessionSecurityToken(genClaim, "test mobile", DateTime.UtcNow, DateTime.UtcNow.AddDays(1), true);
FederatedAuthentication.SessionAuthenticationModule.AuthenticateSessionSecurityToken(token, true);
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", "/Default/IndexRedirectFromMobile");
Response.End();
}
}
}
What ends up happening is when setting the user to the GeneralPrincipal above, we have HttpContext.Current.Request.IsAuthenticated set to true. However, after we try to redirect the user to the correct landing page, the request is no longer authenticated and they get caught in an infinite loop.
What can we do to prevent this from happening?
A simplest way would be to write the token to a cookie
var token = FederatedAuthentication.SessionAuthenticationModule.CreateSessionSecurityToken(genClaim, "test mobile", DateTime.UtcNow, DateTime.UtcNow.AddDays(1), true);
FederatedAuthentication.SessionAuthenticationModule.WriteSessonTokenToCookie( token );
You need to remember that the client must support cookies. Depending on the actual client technology you use, this can be easier or harder.
However, you don't need to use the SAM module to retain the session. You can use Forms Authentication, a custom authentication header or anything else.

How to login to Instagram from codebehind?

I need to show images of a specific instagram user on my webpage.
As stated in the Instagram API documentation I need to get authenticated to be able to "browse" a user's feed.
"We only require authentication in cases where your application is making requests on behalf of a user (commenting, liking, browsing a user’s feed, etc.)."
(http://instagram.com/developer/authentication/)
So as stated in the API documentation, I send a request to this URL:
https://instagram.com/oauth/authorize/?display=touch&client_id=[ClientID]
&redirect_uri=[callbackuri]/&response_type=token
to be redirected to another URL: http://your_redirect_uri?code=CODE to be able to get the access_token (CODE) to be able to call the instagram RESTful services with it.
The problem is that if my website visitor is not logged in to Instagram, he/she will be forwarded to a login page to authenticate first and only then I can get an access token.
My question is: how can I bypass this login page by automatically login with my application's instagram account from the codebehind (or probably by javascript!)?
I am using C# and Instasharp(http://instasharp.org/) by the way.
Any ideas?
Thank you in advance!
first of create Developer app in Instagram and get consumerkey & consumersecret and set path call back url somthing link http://localhost:3104/Instagram.aspx
private void Authentication()
{
string rest = string.Empty;
GlobusInstagramLib.Authentication.ConfigurationIns config = new GlobusInstagramLib.Authentication.ConfigurationIns("https://instagram.com/oauth/authorize/", ConfigurationManager.AppSettings["consumerKey"], ConfigurationManager.AppSettings["consumerSecret"], ConfigurationManager.AppSettings["callbackurl"], "https://api.instagram.com/oauth/access_token", "https://api.instagram.com/v1/", "");
oAuthInstagram _api = oAuthInstagram.GetInstance(config);
rest = _api.AuthGetUrl("likes+comments+basic+relationships");
Response.Redirect(rest);
}
Automatic redirect on this page and call this code
public void Instagram()
{
string code = (String)Request.QueryString["code"];
oAuthInstagram objInsta = new oAuthInstagram();
GlobusInstagramLib.Authentication.ConfigurationIns configi = new GlobusInstagramLib.Authentication.ConfigurationIns("https://api.instagram.com/oauth/authorize/", ConfigurationManager.AppSettings["consumerKey"], ConfigurationManager.AppSettings["consumerSecret"], ConfigurationManager.AppSettings["callbackurl"], "http://api.instagram.com/oauth/access_token", "https://api.instagram.com/v1/", "");
oAuthInstagram _api = new oAuthInstagram();
_api = oAuthInstagram.GetInstance(configi);
AccessToken access = new AccessToken();
access = _api.AuthGetAccessToken(code);
string accessToken = access.access_token;
string id =access.user.id;
}
you will get token and user id

Categories

Resources