My application is using the AD Authentication for Login using LDAP URL. All was fine until our SA told us to change the URL to LDAPS. Once I added the URL as LDAPS it throws an exception and does not allow users to Login. Please help me in this.
Working LDAP URL: LDAP://reg1.abc.com
LDAPS URL (NEW) : LDAPS://reg1.abc.com (Not working once changed)
Below is the code to Authenticate user through LDAP.
public static SearchResult AuthenticateUser(string userName, string password)
{
var directoryEntry = new DirectoryEntry(ConfigurationManager.AppSettings["ActiveDirectoryPath"], userName, password, AuthenticationTypes.Secure);
var directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = "(samaccountname=" + userName + ")";
var result = directorySearcher.FindOne();
return result;
}
That's a common question that might be already answered at Unknown Error (0x80005000) with LDAPS Connection. Follow that link and try to add port 636 and custom certificate validation:
LdapConnection con = new LdapConnection(new LdapDirectoryIdentifier("server", port));
con.SessionOptions.SecureSocketLayer = true;
con.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);
con.Credential = new NetworkCredential(String.Empty, String.Empty);
con.AuthType = AuthType.Basic;
con.Bind();
In the given example Credential is using empty strings, that might need to be changed by real login/password if required.
I have an MVC 5 web application and can login with a Login.cshtml page and get a cookie and the login works fine. But, I would like to do a login with the Web API and then (maybe) set a cookie so that I am logged in for my MVC pages... (or login with the MVC login and then access the Web API) however the web api returns a bearer token and not a cookie token... so this doesn't work. Is there a way to combine the use of authentication both for my MVC pages and for my Web API pages?
UPDATE:
This isn't really a code issue, more of a conceptual issue.
Normal MVC web pages examine a cookie named, by default, ".AspNet.ApplicationCookie" to determine the requesters identity. This cookie is generated by calling ApplicationSignInManager.PasswordSignInAsync.
WebAPI calls, on the other hand, examine the requests headers for an item named Authorization... and uses that value to determine the requesters identity. This is returned from a WebAPI call to "/Token".
These are very different values. My website needs to use both MVC pages and WebAPI calls (to dynamically update those pages)... and both need to be authenticated to perform their tasks.
The only method I can think of is to actually authenticate twice... once with a WebAPI call and again with the Login post. (see my Answer below).
This seems very hacky... but I don't understand the authorization code enough to know if there is a more proper way of accomplishing this.
The best way to achieve this, is to have an authorization server (a Web API generating a token) and token consumption middle-ware in your MVC project. IdentityServer should help. However I have done it like this:
I built an authorization server using JWT with Web API and ASP.Net Identity as explained here.
Once you do that, your Web APIs startup.cs will look like this:
// Configures cookie auth for web apps and JWT for SPA,Mobile apps
private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
// Cookie for old school MVC application
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true, // JavaScript should use the Bearer
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/api/Account/Login"),
CookieName = "AuthCookie"
};
// Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
app.UseCookieAuthentication(cookieOptions);
OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(ConfigurationManager.AppSettings["JWTPath"])
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
You can find the CustomOAuthProvider and CustomJwtFormat classes here.
I wrote a consumption logic (i.e. middleware) in all my other APIs (Resource servers) that I wanted to secure using the same token. Since you want to consume the token generated by the Web API in your MVC project, after implementing the authorization server, you need to the following:
In your MVC app, add this in startup.cs:
public void Configuration(IAppBuilder app)
{
ConfigureOAuthTokenConsumption(app);
}
private void ConfigureOAuthTokenConsumption(IAppBuilder app)
{
var issuer = ConfigurationManager.AppSettings["AuthIssuer"];
string audienceid = ConfigurationManager.AppSettings["AudienceId"];
byte[] audiencesecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);
app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieName = "AuthCookie" , AuthenticationType=DefaultAuthenticationTypes.ApplicationCookie });
//// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Passive,
AuthenticationType = "JWT",
AllowedAudiences = new[] { audienceid },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, audiencesecret)
}
});
}
In your MVC controller, when you receive the token, de-serialize it and generate a cookie from the access token:
AccessClaims claimsToken = new AccessClaims();
claimsToken = JsonConvert.DeserializeObject<AccessClaims>(response.Content);
claimsToken.Cookie = response.Cookies[0].Value;
Request.Headers.Add("Authorization", "bearer " + claimsToken.access_token);
var ctx = Request.GetOwinContext();
var authenticateResult = await ctx.Authentication.AuthenticateAsync("JWT");
ctx.Authentication.SignOut("JWT");
var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(applicationCookieIdentity);
Generate a machine key and add it in web.config of your Web API and ASP.Net MVC site.
With this, a cookie will be created and the [Authorize] attribute in the MVC site and the Web API will honor this cookie.
P.S. I have done this with a Web API issuing JWT (Authorization server or Auth & resource server) and was able to consume it in an ASP.Net MVC website, SPA Site built in Angular, secure APIs built in python (resource server), spring (resource server) and an Android App.
Ugg... what I had to do was use the Login.cshtml form and override the submit... make an Ajax call to get the WebApi bearer token... and then do the form submit to get the actual MVC cookie. So, I'm actually making two login requests... one for the WebApi token and the other for the MVC cookie.
Seem pretty hacky to me... it would be nice if there was some way to sign in to MVC using the bearer token... or a call to the WebApi that would return me a cookie that I can use for normal MVC page requests.
If anyone has a better way I would love to hear it.
This is script code that I added to Login.cshtml:
$(document).ready(function () {
$('form:first').submit(function (e) {
e.preventDefault();
var $form = $(this);
var formData = $form.serializeObject(); // https://github.com/macek/jquery-serialize-object
formData.grant_type = "password";
$.ajax({
type: "POST",
url: '#Url.Content("~/Token")',
dataType: "json",
data: formData, // seems like the data must be in json format
success: function (data) {
sessionStorage.setItem('token', data.access_token);
$form.get(0).submit(); // do the actual page post now
},
error: function (textStatus, errorThrown) {
}
});
});
});
I assume what you're trying to do is have pages served by MVC have javascript that makes calls to Web API methods. If you're using ASP.NET Identity to handle authentication (which it looks like you're doing), then MVC should be using OAuth tokens that can be passed to Web API for authentication.
Here's a snippet from some javascript code that works for me in a similar situation:
var token = sessionStorage.getItem('access_token');
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: <GET/POSt/...>,
url: <your api>,
headers: headers
}).done(function (result, textStatus) {
I have similar case with you, but i use a different way to authenticate.
I have a web and an api, which all for intranet users. I do not use user's identity to pass web and api. Instead, i created a individual web account, and every time web will use this special account to connect to api.
Because, we also need to make sure that users should not connect to api directly. They should only connect to web ui.
Hope this help you.
From your comments above, from what I understand, you have a scenario wherein you perform login through browser but also have to invoke web-api methods using ajax calls.
The browser calls are session-cookie based. While the ajax calls from the browser would have the session cookie in the header, what is required is the authentication header to be present for the web-api to perform validation.
So on a successful login you'd also have to generate a web-api based token, set it as a cookie (that is accessible by javascript) and then while making ajax calls, pick it up from the cookie and include it as header in your 'Authorization' header.
I upload my first ASP.NET MVC application to App Harbor, that uses FormsAuthentication to simple authentication of the user.
As usual on local machine operation that required authentications performes well, at the moment I tun them on AppHarbor, they failed.
I checked that authentication cookie released on access is send with the request, as it visible from image:
and my server side authentication code looks like
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
user.UserName,
DateTime.Now,
DateTime.Now.AddDays(1),
true,
user.UserName
);
string encTicket = FormsAuthentication.Encrypt(authTicket);
this.Response.Cookies.Add(
new HttpCookie(
FormsAuthentication.FormsCookieName,
encTicket)
{ Expires = authTicket.Expiration });
I read different posts from AppHarbor blogs like ASP.NET Forms Authentication Considered Broken, it says "harmflul" and not that it's not working.
So, what I do wrong here ?
I do have authorize attribute applied on my Web API.
I am calling Web API from MVC4 application in which I am using standard cookie based authentication.
I need to call Web API method on controllers from integration tests but because authorize attribute is applied I will always receive unauthorized exception.
What is the best way to solve this problem ?
PS. I don't want (need) to use other methods of authentication such as APIKey,Token in Auth Header and similar...
First of all, one key element in order to answer this question is to know what kind of authentication mechanism you use. For example, if you use basic auth, you can send the credentials when you are integration testing:
[Fact]
public async Task FooTest() {
var username = "user";
var password = "supersecret";
// construct your config here as I do below.
// RouteConfig and WebAPIConfig are my own classes
var config = new HttpConfiguration();
RouteConfig.RegisterRoutes(config);
WebAPIConfig.Configure(config);
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/cars");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue(
"Basic", EncodeToBase64(string.Format("{0}:{1}", username, password)));
using (var httpServer = new HttpServer(config))
using (var client = new HttpClient(httpServer)) {
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsAsync<Car>();
// do you test now...
}
}
private static string EncodeToBase64(string value) {
byte[] toEncodeAsBytes = Encoding.UTF8.GetBytes(value);
return Convert.ToBase64String(toEncodeAsBytes);
}
Of course, your handler which handles the authentication should be able to authenticate you with those credentials.
On the other hand, as you will be hosting the application in memory, setting an authenticated principal to the Thread.CurrentPrincipal would be another option but wouldn't be my favorite option here.
I am using the new webapi.
Now I don't know if I am doing this correctly but I am trying to setup my api to return an authentication cookie within the HttpResponseMessages header to use on another an mvc application.
I am using the FormsAuthenticationTicket as I think its what I need to use like
public HttpResponseMessage Get(LoginModel model)
{
if (model.UserName == "bob")
{
// if (Membership.ValidateUser(model.UserName, model.Password))
// {
var msg = new HttpResponseMessage(HttpStatusCode.OK);
var expires = DateTime.Now.AddMinutes(30);
var auth = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, expires,
model.RememberMe,"password",
FormsAuthentication.FormsCookiePath);
var cookie = new HttpCookie("user");
cookie.Value = FormsAuthentication.Encrypt(auth);
cookie.Domain = "localhost";
cookie.Expires = expires;
msg.Headers.Add("result",cookie.Value);
return msg;
// }
}
return new HttpResponseMessage(HttpStatusCode.Forbidden);
//else
//{
// return "The user name or password provided is incorrect.";
//}
}
now within my login controller on my mvc application I call the service and get the data value from the header I set in the api controller.
string data = response.Headers["result"].ToString();
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(data);
Everytime I try running the FormsAuthentication.Decrypt I keep getting an error
Unable to validate data.
I assume its due to when the api encrypts the data it uses some kind of key that the website doesn't know about. Am I right?
Can someone help out?
Thank you
I assume its due to when the api encrypts the data it uses some kind
of key that the website doesn't know about. Am I right?
FormsAuthentication.Encrypt and Decrypt methods use the machine key. So make sure you have configured the same key for both your Web API web application and the consuming ASP.NET MVC application.
You could also take a look at the following article which illustrates how you could use OAuth 2.0 with the Web API.