redirect on another page on button click - asp.net-mvc-5

I am creating a web app and I have 2 textboxes and one button with an input field
<input id="Login" type="submit" onclick="location.href='#Url.Action("loggedin","logincontroller")'" style="" width="200" height="34" value="submit" />
and my controller looks like
public ActionResult loggedin(string role, string username, string password)
{
webservice.loginservice a= new webservice.loginservice();
a.getlogintype(role, username, password);
return View();
}
with my webservice
[WebMethod]
public string getlogintype(string role, string username, string password)
{
string strtru="";
string strfalse="";
sqlcon;
SqlCommand cmd = new SqlCommand("select * from [admin] where userid='" + username + "' and pass ='" + password + "'", con);
con.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
strtru = "true";
}
else
{
strfalse = "false";
}
con.Close();
}
My controller is calling the webservice and now I want to know how to redirect the page on successful validation. This is my first application using mvc I know there are many mistakes in this app(please let me know all the mistakes).
I am creating the application on mvc 5 and I am only using input fields not #Html syntax because I want to design it like(beta2.hti-india.com) this app is created by me on asp.net c#.

your web service code looks good.
changes in your code.
public ActionResult loggedin(string role, string username, string password)
{
webservice.loginservice a= new webservice.loginservice();
string result = a.getlogintype(role, username, password);
if(result == "true")
{
// redirect to your application home page or other page
return RedirectToAction("OtherAction", "Controller");
}
else
{
return View();
}
}
try to use this is better way for .cshtml or View
#using (Html.BeginForm("loggedin", "controller", new { ReturnUrl = "" }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<!-- your textbox here-->
<input id="Login" type="submit" value="submit">
}

in your action method loggedin(..) you should return a new view by using RedirectToAction()
return RedirectToAction("MyAction", "MyController");

Related

Solving XSS issues

I am trying to build an MVC application and have been told it is not a good way to retrieve data and is susceptible to cross-site scripting. I have never done security and have been trying to learn as well but I cannot wrap my head around it.
I am guessing there are several flaws here. Is there any particular encoding I can use?
I haven't pasted the entire code here but trying to figure out where I can stop the XSS attacks.
Model and View Model
namespace ThePeopleSearchApplication.Models
{
public class UserViewModel
{
public string UID{ get; set; }
public string FName{ get; set; }
public string LName{ get; set; }
public string Email { get; set; }
public string Status{ get; set; }
}
public class UserModel
{
public string UID{ get; set; }
public string FName{ get; set; }
public string LName{ get; set; }
public string Email { get; set; }
public string Status{ get; set; }
}
}
Controller
namespace ThePeopleSearchApplication.Controllers
{
public class MyController : Controller
{
// GET: My
public ActionResult Index()
{
return View();
}
[ValidateInput(false)] //has been added to understand XSS better
public ActionResult SearchUserAjax(string userId)
{
UserModel myUser = fetchUserFromLdap(userId);
return Content("{\"message\": \"search for userId: " +
userId + " result\", \"result\": " + convertToJson(myUser) + " }");
}
private string convertToJson(UserModel myUser)
{
return "{ \"userId\": \"" + myUser.UserId + "\", \"FirstName\": \"" +
myUser.FirstName + "\", \"LastName\": \"" + myUser.LastName + "\", \"Email\": \"" +
myUser.Email + "\", \"Status\": \"" + myUser.Status + "\"}";
}
[ValidateInput(false)] //has been added to understand XSS better
public ActionResult SearchUser(string userId)
{
UserModel myUser = fetchUserFromLdap(userId);
var viewModel = new UserViewModel
{
UID = userId,
FName = myUser.FirstName,
LName = myUser.LastName,
Email = myUser.Email,
Status = myUser.Status,
};
return this.View(viewModel);
}
private UserModel fetchUserFromLdap(string userId)
{
var retVal = new UserModel();
if (String.IsNullOrEmpty(userId))
{
retVal.UID = "N/A";
retVal.FName = "N/A";
retVal.LName = "N/A";
retVal.Email = "N/A";
retVal.Status = "N/A";
}
else
{
retVal.UID = userId;
retVal.FName = "FirstName";
retVal.LName = "LastName";
retVal.Email = "email#example.com";
retVal.Status = "<div style=background-color:#F00800>My Status</div>";
}
return retVal;
}
}
}
View
#model ThePeopleSearchApplication.Models.UserViewModel
#{
ViewBag.Title = "Search result for user: " + Model.UserId;
var ulId = "ul-id" + Model.UserId;
var formId = "form" + Model.UserId;
}
<html>
<head>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
</head>
<body>
<h1>Search result for user: #Model.UserId</h1>
<ul id="#Html.Raw(ulId)">
<li>#Model.FirstName</li>
<li>#Model.LastName</li>
<li>#Model.Email</li>
<li>#Html.Raw(Model.Status)</li>
</ul>
<form id=#formId name=#formId action=/My/SearchUser enctype="multipart/form-data">
<input type="text" name="userId" />
<input type="submit" />
</form>
<script type="text/javascript">
var theForm = document.#formId;
$(theForm).submit(function() {
alert('Valid form');
return true;
});
// just to demonstrate potential usage $(theForm).submit();
</script>
<div>
Ajax search:
<form id="ajax-search" name="ajax-search">
<input type="text" name="userId" />
<input type="submit" />
</form>
<script>
$("#ajax-search").submit(function() {
var url = "/My/SearchUserAjax"; // the script where you handle the form input.
$.ajax({
type: "POST",
url: url,
data: $("#ajax-search").serialize(), // serializes the form's elements.
success: function(data)
{
var obj = JSON.parse(data);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.message); // show response from the php script.
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.userId);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.FirstName);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.LastName);
$('#ajax-search').append('<hr/>');
$('#ajax-search').append(obj.result.Status);
$('#ajax-search').append('<hr/>');
}
});
return false; // avoid to execute the actual submit of the form.
});
</script>
</div>
</body>
</html>
The principle problem is if the User controls some data that you render to the page in an unsafe way. Whether that be from their name (my name is <script>function() { nasty stuff is happening here... }</script>) or any other content.
I take the following approach, look at your output (or better think ahead about it) and see if it's a problem at each stage:
Let Razor do it, by default Razor handles encoding of all HTML
characters on the page, this doesn't apply if you use an
IHtmlString so avoid this Type (or methods that return it like
Html.Raw()) so #("<script>nastyThings()</script>") is a string so that will be encoded, and the script will not run
If it's broken, that means your string has some HTML/JS in it that
you actually want to render. So try and move that directly onto the
Razor template (HTML/JS) or obtain it via a link (JS)
Instead of the whole string being user controlled "<element onclick="javascript:alert('trouble')"></element>" with template #Html.Raw(Model.UserBadString)
Make the template <element onclick="mySafeJsFunction()">#Model.UserSafeString</element>", this takes control of the JS function away from the User, and leaves them with a Razor encoded parameter that they can't do XSS with
You want the User to have control over the HTML, then you will have to sanitise the string on output to the page, by using something like (https://github.com/mganss/HtmlSanitizer)
So the template could be #Html.Raw(sanitizer.Sanitize(Model.UserBadString)) but you'd probably want to do something nicer than that, good coding practice etc. The main point is that the string is sanitised
As an aside, make sure you keep a very close aye on usages of properties such as .innerHTML in JS (or the dreaded jQuery .html() which calls eval()), as if these take in user controlled content you'll have the exact same problem. But the same steps can be applied, (1) use .innerText instead, or (3) otherwise use a purification library on the string like DOMPurify before giving it to the JS (https://github.com/cure53/DOMPurify). Unfortunately in this case option (2) is not recommended, since whatever is left will have to be made safe by you or I, I'd rather trust DOMPurify to do it :)

Umbraco + OpenId + Thinktecture Puzzle

I have been trying to figure this out for 2 days now and have decided it time to ask for help. Here is the setup:
Running Umbraco 7.5.6 with the following packages:
UmbracoIdentity 5.0.0
UmbracoCms.IdentityExtensions 1.0.0
UmbracoCms.IdentityExtesnions.AzureActiveDirectory 1.0.0
We are also running a Thinktecture SSO Server
IdentityServer3
Here are the requirements:
Back Office Users must log in via AAD or Internal Users (this is done
and working)
Members must log in via the Thinktecture SSO Server
If the member is not on the home page, they must be redirected back to whatever page they were attempting to access after successful login
This all seems straight forward so here is the code I have so far.
This is the Middleware I wrote to stick into the Owin Startup Process:
public static IAppBuilder ConfigureFrontEndSsoAuth(this IAppBuilder app)
{
//var postLoginRedirectUrl = "";
var ssoOptions = new OpenIdConnectAuthenticationOptions
{
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
Authority = Config.SsoAuthority,
ClientId = Config.SsoClientId,
CallbackPath = new PathString("/umbraco/surface/UmbracoIdentityAccount/ExternalLoginCallback"),
RedirectUri = "http://bacp.dev/umbraco/surface/UmbracoIdentityAccount/ExternalLoginCallback",
ResponseType = Config.SsoResponseType,
Scope = Config.SsoScope,
AuthenticationMode = AuthenticationMode.Passive,
Notifications = new OpenIdConnectAuthenticationNotifications()
{
SecurityTokenValidated = async x =>
{
// Will deal with Claims soon
}
}
};
ssoOptions.Caption = "Member SSO";
ssoOptions.AuthenticationType = String.Format(CultureInfo.InvariantCulture, Config.SsoAuthority);
ssoOptions.SetExternalSignInAutoLinkOptions(new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true));
app.UseOpenIdConnectAuthentication(ssoOptions);
return app;
}
Here are my two controller methods:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl = null)
{
if (returnUrl.IsNullOrWhiteSpace())
{
returnUrl = Request.RawUrl;
}
// Request a redirect to the external login provider
return new ChallengeResult(provider,
Url.SurfaceAction<UmbracoIdentityAccountController>("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
[HttpGet]
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl = null)
{
if (String.IsNullOrEmpty(returnUrl))
{
returnUrl = "/";
}
var loginInfo = await OwinContext.Authentication.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
//go home, invalid callback
return RedirectToLocal(returnUrl);
}
// Sign in the user with this external login provider if the user already has a login
var user = await UserManager.FindAsync(loginInfo.Login);
if (user != null)
{
await SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl);
}
else
{
// If the user does not have an account, then prompt the user to create an account
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
}
}
And last, the login action on the view:
<form action="/Umbraco/surface/UmbracoIdentityAccount/ExternalLogin" method="post">
#Html.AntiForgeryToken()
<input type="hidden" name="provider" value="#Config.SsoAuthority"/>
<input type="hidden" name="returnUrl" value="#Request.RawUrl"/>
<input type="submit" class="profile-summary__link" value="Login"/>
</form>
Now, this is where I get lost and I am either just missing something really small or something.
The following steps are the issue at hand:
The Umbraco Page Loads up
I am able to click on "Login" which redirects to the SSO Server
If I am not logged in, I login | If I am logged in, it validated my cookie and sends me back
It claims it's sending me to ExternalLoginCallback but if I put a breakpoint on the controller method it never hits hit.
It then tries to redirect back to ExternalLogin (not sure where it's getting this from)
Any help or suggestions would be great.

Bot Framework - Sign-In Card, how get auth result

working with Microsoft Bot Framework V3 I started using Sign-In Cards.
I did a simple cut and paste from example code page into my code and let's say it works (compiles):
https://docs.botframework.com/en-us/csharp/builder/sdkreference/attachments.html
What was expected is a behavior similar to oauth process so to be redirected to , do it's own stuffs and return the auth resul including all informations.
What I realized is that it simply open a new web page to the link I provided, that's all...
No other code founded elsewere...
So far it seems useless as I could provide the link simply with normal messages based on this behavior, also there is no communication with the bot.
Did I missed something?
Option 1) Custom Authentication using Windows Active Directory
I have made a custom authentication technique which queries Windows AD using Kerberos LDAP Protocol and using PrincipalContext class.
Firstly, in Root Dialog save the context of the chat in the ConversationReference and encode it using Base64 encoding.
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.ConnectorEx;
using System.Threading;
namespace ADAuthBot.Dialogs
{
[Serializable]
public class RootDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Welcome to Auth Bot!");
context.Wait(MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var message = await result as Activity;
ConversationReference conversationReference = message.ToConversationReference();
string username = string.Empty;
context.PrivateConversationData.SetValue<string>("usertext", message.Text);
if (!context.PrivateConversationData.TryGetValue<string>("Username", out username))
{
string encodedCookie = UrlToken.Encode(conversationReference);
await AuthDialog.createPromptForLogin(context, encodedCookie);
}
else
{
context.Call(this, ResumeAfter);
}
}
private async Task ResumeAfter(IDialogContext context, IAwaitable<object> result)
{
var item = await result;
context.Wait(MessageReceivedAsync);
}
}
}
Next, we come to the Auth Dialog in which we create a Sign-In Card and give the URL page that needs to be opened on the click of the authenticate button.
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.ConnectorEx;
using System.Threading;
using System.Collections.Generic;
using System.Configuration;
namespace ADAuthBot.Dialogs
{
[Serializable]
public class AuthDialog: IDialog<object>
{
static string authenticationUrl = string.Empty; //Authentication URL is the MVC View URL, which will have the username and password window.
static string callbackurl = string.Empty;
static AuthDialog()
{
authenticationUrl = ConfigurationManager.AppSettings["AuthenticationUrl"];
callbackurl = ConfigurationManager.AppSettings["AuthCallbackUrl"];
}
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
}
public static async Task createPromptForLogin(IDialogContext context, string encodedCookie)
{
IMessageActivity response = context.MakeMessage();
response.Attachments = new List<Attachment>();
SigninCard signincard = new SigninCard()
{
Text = "Click here to sign in",
Buttons = new List<CardAction>() {
new CardAction()
{
Title = "Authentication Required",
Type = ActionTypes.OpenUrl,
Value = $"{authenticationUrl}?{encodedCookie}"
}
}
};
response.Attachments.Add(signincard.ToAttachment());
await context.PostAsync(response);
}
}
}
Next I made a MVC view which inputs your username and password and sends it to the ADAuthController to query it against the Windows Active Directory.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ADAuthService.Controllers
{
public class LoginADController : Controller
{
// GET: LoginAD
[Route("Login")]
public ActionResult LoginUsingAD()
{
return View();
}
}
}
Next I created a simple Razor view which uses jQuery AJAX call to send username and password by encoding it in base64 encoding by using Javascript's btoa() function.
<script src="~/scripts/jquery-3.2.1.min.js"></script>
<script src="~/scripts/bootstrap.min.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<script>
$(function () {
$("#txtUserName").html("");
$("#txtPassword").html("");
function make_base64_auth(username, password) {
var tok = username + ' ' + password;
var hash = btoa(tok);
return hash;
}
$("#btnSubmit").click(function () {
var userName = $("#txtUserName").val();
var passWord = $("#txtPassword").val();
var conversationReference = $(location).attr('search');
console.log(conversationReference);
var dataToBeSent = {
"ConversationReference": conversationReference,
"HashedUserCredentials": make_base64_auth(userName, passWord)
};
$.ajax({
url: "http://localhost:1070/api/Login",
method: "POST",
dataType: "json",
data: dataToBeSent,
contentType: "application/json",
crossDomain: true,
success: function (data) {
debugger;
console.log(data);
if(!$.isEmptyObject(data))
alert(data);
},
error: function (jqXHR, textStatus, errorThrown) {
debugger;
if (!$.isEmptyObject(jqXHR))
alert("Something happened wrong because: " + jqXHR.responseText);
}
});
});
});
</script>
<div class="panel-info">
<div class="panel panel-heading">
Enter your credentials
</div>
<div class="panel panel-body">
<div class="form-group">
<label for="username">Username: </label> <input id="txtUserName" type="text" placeholder="Enter username" required class="form-control" />
<label for="password">Password: </label> <input id="txtPassword" type="password" placeholder="Enter password" required class="form-control" />
<button id="btnSubmit" class="btn btn-info">Submit</button>
<button id="btnReset" class="btn btn-danger" type="reset">Reset</button>
</div>
</div>
</div>
I made a model class to store whether a user is identified or not.
namespace ADAuthService.Models
{
public class AuthenticatedUser
{
public string AuthenticatedUserName { get; set; } = string.Empty;
public bool IsAuthenticated { get; set; } = false;
}
}
and a model class to get details from MVC View.
namespace ADAuthService.Models
{
public class UserDetailsHashed
{
public string HashedUserCredentials { get; set; } = string.Empty;
public string ConversationReference { get; set; } = string.Empty;
}
}
Now the main content is to write a method which queries the Windows Active Directory by taking username, password and domain as input. After authenticating I am using the Service URL to send the authenticated user's name to the bot framework by resolving the scope using Autofac IoC Container.
using ADAuthService.Models;
using Autofac;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Connector;
using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;
namespace ADAuthService.Controllers
{
public class ADAuthController : ApiController
{
[NonAction]
private void extractUserDetailsFromHash(UserDetailsHashed userDetails, out string username, out string password, out string conversationReference)
{
try
{
string[] userCredentials = userDetails.HashedUserCredentials.Split(' ');
byte[] userCredentialsBinary = Convert.FromBase64String(userCredentials.Last());
string decodedString = Encoding.UTF8.GetString(userCredentialsBinary);
string[] decodedStringArray = decodedString.Split(' ');
username = decodedStringArray[0];
password = decodedStringArray[1];
string[] userConversationReference = userDetails.ConversationReference.Split('?');
conversationReference = userConversationReference[1];
}
catch (Exception ex)
{
throw ex;
}
}
[NonAction]
private Task<AuthenticatedUser> ValidateUserAgainstAD(string username, string password)
{
AuthenticatedUser user = new AuthenticatedUser();
return Task.Run<AuthenticatedUser>(() => {
string ADDisplayName = string.Empty;
try
{
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName))
{
bool isValidCredentials = ctx.ValidateCredentials(username, password, ContextOptions.Negotiate);
// Additional check to search user in directory.
if (isValidCredentials)
{
UserPrincipal prUsr = new UserPrincipal(ctx);
prUsr.SamAccountName = username;
PrincipalSearcher srchUser = new PrincipalSearcher(prUsr);
UserPrincipal foundUsr = srchUser.FindOne() as UserPrincipal;
if (foundUsr != null)
{
user.AuthenticatedUserName = foundUsr.DisplayName;
user.IsAuthenticated = isValidCredentials;
}
}
else
throw new AuthenticationException($"Couldn't query no such credentials in Microsoft Active Directory such as Username: {username} and Password: {password}. Try entering a valid username and password combination.");
}
}
catch (Exception ex)
{
throw ex;
}
return user;
});
}
[NonAction]
public async Task ReplyToBot(string userName, string encodedConversationReference)
{
Activity reply = null;
ConversationReference decodedConversationReference = UrlToken.Decode<ConversationReference>(encodedConversationReference);
bool writeSuccessful = false;
IMessageActivity msgToBeSent = decodedConversationReference.GetPostToUserMessage();
using (ILifetimeScope scope = DialogModule.BeginLifetimeScope(Conversation.Container, msgToBeSent))
{
try
{
IConnectorClient client = scope.Resolve<IConnectorClient>();
IStateClient sc = scope.Resolve<IStateClient>();
BotData userData = sc.BotState.GetPrivateConversationData(msgToBeSent.ChannelId, msgToBeSent.From.Id, msgToBeSent.Id);
userData.SetProperty("Username", userName);
sc.BotState.SetPrivateConversationData(msgToBeSent.ChannelId, msgToBeSent.Conversation.Id, msgToBeSent.Id, userData);
writeSuccessful = true;
}
catch (Exception ex)
{
writeSuccessful = false;
throw ex;
}
if (!writeSuccessful)
{
msgToBeSent.Text = string.Empty;
await Conversation.ResumeAsync(decodedConversationReference, msgToBeSent);
}
if (writeSuccessful)
{
reply = msgToBeSent as Activity;
var connector = new ConnectorClient(new Uri(msgToBeSent.ServiceUrl));
reply.Text = $"Welcome {userName}!";
connector.Conversations.SendToConversation(reply);
}
}
}
[HttpPost]
[EnableCors("*", "*", "*")]
[Route("api/Login")]
public async Task<HttpResponseMessage> Login(UserDetailsHashed userDetails)
{
try
{
string username = string.Empty;
string password = string.Empty;
string conversationReference = string.Empty;
AuthenticatedUser userToBeAuthenticated = new AuthenticatedUser();
extractUserDetailsFromHash(userDetails, out username, out password, out conversationReference);
userToBeAuthenticated = await ValidateUserAgainstAD(username, password);
if (userToBeAuthenticated.IsAuthenticated)
{
await ReplyToBot(userName: userToBeAuthenticated.AuthenticatedUserName, encodedConversationReference: conversationReference);
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent($"Thanks, {userToBeAuthenticated.AuthenticatedUserName} you're now logged in!") };
}
else
{
return new HttpResponseMessage { StatusCode = HttpStatusCode.Forbidden, Content = new StringContent($"Couldn't query no such credentials in Microsoft Active Directory such as Username: {username} and Password: {password}. Try entering a valid username and password combination.") };
}
}
catch(Exception ex)
{
throw new HttpResponseException(new HttpResponseMessage() { StatusCode = HttpStatusCode.Forbidden, Content = new StringContent($"Couldn't query no such credentials in Microsoft Active Directory. Try entering a valid username and password combination.") });
}
}
}
}
Option 2) Use the patterns described in the following link:
MSDN Magic number Pattern
No, you didn't miss anything. The Sign-In card just provide a visual way of showing to the user that it needs to authenticate. Each channel will display the Sign-In card differently; depending on the channel implementation.
To implement the OAuth process, I'd recommend you to take a look to AuthBot.
AuthBot is a .Net library for Azure Active Directory authentication on
bots built via Microsoft Bot Framework.
Even if you are not using AAD, the library is still useful to get the idea on how the OAuth process can be implemented. Aditionally, AuthBot is also using Sign-In card in some scenarios to ask the user for authentication (see this code).
There are other samples that can also help you to understand how to build the OAuth process:
Simple Facebook Auth Sample
GraphBot

Pass multiple pass values to RedirectToAction in MVC 5

I am developing the website in MVC. I want to display details record one by one. The next record to be displayed when user clicks the Submit Button.
Kindly advise for the same
Code in Controller
// GET: Member_Details
public ActionResult Member_Details(int sysmemberid , string type)
{
Member_Details obj = new Member_Details();
obj=obj.getMemberDetails(Convert.ToInt64(Session["Id"]), sysmemberid, type);// assign values to model
Session["sysmemberid"] = sysmemberid;
Session["type"] = type;
Session["Next"] = obj.next;
return View(obj);
}
[HttpPost]
public void Member_Details(Member_Details obj ,string command)
{
string sysmemberid = Session["sysmemberid"].ToString();
string type1 = Session["type"].ToString();
string sqlQuery = "";
int next = Convert.ToInt32(Session["Next"]);
RedirectToAction("Member_Details", new { sysmemberid = next, type = type1 });
}
View Code :
#using (Html.BeginForm("Member_Details", "Member_Details", FormMethod.Post, new { id = "submitForm" }))
{
// Code to bind model
<button type="submit" id="btnSave" name="command" value="invite" class="btn btn-lg btn-primary btn-block link dtlSubmit">Connect</button>
}
It look like you already have the logic to get the next item and are building the ReditectToAction, however it doesn't look like you are returning it.
Add the ActionResult return value to the Member_Details that handles the POST:
public ActionResult Member_Details(Member_Details obj ,string command)
And return your RedirectToAction:
return RedirectToAction("Member_Details", new { sysmemberid = next, type = type1 });

MVC 5 ASP.NET Identity 2: Capture user's preference for "remember me" in ExternalLogin

I am using the Identity 2.0 Sample.
I get that by setting isPersistent to true in ExternalLoginCallback action method, the browser will automatically log the user in the next time (within limits) they visit using the same browser. I know that if the user's "remember me" preference was captured and passed to the ExternalLogin action method that it could be put into returnUrl and accessed in ExternalLoginCallback. But how do I get their preference to the ExternalLogin action method?
I don't get in this case how to put a checkbox on the LoginView page and wire things up so that I can process it in the ExternalLogin action method. How can I accomplish this?
Check out the AccountController.ExternalLoginConfirmation action and note the call to await SignInHelper.SignInAsync(user, isPersistent: false, rememberBrowser: false). You can set those values to true, or you can update the ExternalLoginConfirmationViewModel and corresponding ExternalLoginConfirmation view to let the user decide.
BTW: isPersistent will persist the users session across closing and reopening their browser. The rememberBrowser argument is particular to two factor authentication and it sounds like should be left false for your circumstance.
Tangentially related Supporting remember me with two factor authentication
Don't delete any code, just change as follows:
In AccountViewModels, edit to match:
public class ExternalLoginViewModel
{
public string Action { get; set; }
public string ReturnUrl { get; set; }
public string RemembermeExtnl { get; set; }
}
In Account Controller, edit to match:
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
ViewBag.RemembermeExtnl = "f";
return View();
}
public ActionResult ExternalLogin(string provider, string returnUrl, string remembermeExtnl)
{
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl, remembermeExtnl = remembermeExtnl }));
}
public async Task<ActionResult> ExternalLoginCallback(string returnUrl, string remembermeExtnl)
{
...
var result = await SignInHelper.ExternalSignIn(loginInfo, isPersistent: remembermeExtnl=="t");
...
}
In Login view, edit to match:
<section id="socialLoginForm">
#Html.Partial("_ExternalLoginsListPartial", new PG.Models.ExternalLoginViewModel() { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl, RemembermeExtnl = ViewBag.RemembermeExtnl })
<input type="checkbox" id="cbxRemExt" /> Remember me
</section>
In Login view, add this:
<script>
// ** change to eq(1) (2 places!) if your social login form is the second form on the page,
// keep as below if first form is your social login form **
$("#cbxRemExt").change(function () {
var isChecked = $(this).is(":checked");
var actionstring = $('form').eq(0).attr('action');
actionstring = actionstring.replace('RemembermeExtnl=' + (isChecked ? 'f' : 't'), 'RemembermeExtnl=' + (isChecked ? 't' : 'f'))
$('form').eq(0).attr('action', actionstring);
});
</script>
In _ExternalLoginListPartial:
string action = Model.Action;
string returnUrl = Model.ReturnUrl;
string remembermeExtnl = Model.RemembermeExtnl;
using (Html.BeginForm(action, "Account", new { ReturnUrl = returnUrl, RemembermeExtnl = remembermeExtnl }))

Resources