forms auth, authenticate against already encrypted password?

T

Tim Mackey

hi,
i'm using forms authentication with a web service, and i have the web
service passing in the password already encrypted in MD5. can i use any of
the built-in FormsAuthentication methods to authenticate with this password?
it works fine if i pass in the plain text password.

e.g. FormsAuthentication.Authenticate("tim", "pass") works fine, but the
following code does not work, by design of course:
FormsAuthentication.Authenticate("tim", "1A1DC91C907325C69271DDF0C944BC72")

i could always dig into the web.config file myself to access the encrypted
password value but i try to avoid that approach where possible.
thanks
tim

p.s. to anyone wondering about using web services with forms auth, it has
limited use and it's a bit of a workaround, but for my app it is invaluable
and much simpler than a custom security solution. set the LoginUrl in
web.config to the web service itself, add Login() and Logout() web methods
that use FormsAuthentication, enable session state on all the web methods,
set a cookie container on the client proxy object, and for each of the web
methods, do a simple check if(!User.Identity.IsAuthenticated) throw new
UnauthorisedAccessException(), etc.
 
D

Dominick Baier

No - you have to pass in the clear text - you should SSL anyways to protect
the webservice and the resulting cookie - so passing a clear text password
in your solution is not a big deal.
p.s. to anyone wondering about using web services with forms auth, it
has limited use and it's a bit of a workaround,

some would say a "hack" ;)
but for my app it is
invaluable and much simpler than a custom security solution. set the
LoginUrl in web.config to the web service itself, add Login() and
Logout() web methods

Also don't forget to handle the timeout scenario.
that use FormsAuthentication, enable session
state on all the web methods,

Why do you need session state? this is not a requirement of FormsAuth.
set a cookie container on the client
proxy object, and for each of the web methods, do a simple check
if(!User.Identity.IsAuthenticated) throw new
UnauthorisedAccessException(), etc.

I would recommend using an <authorization> element in web.config rather than
requiring code in each web method (which can be forgotten)
 
T

Tim Mackey

hi dominick,
yes, it is a hack, but a very useful one!
thanks for the suggestion, good idea to SSL, although my app is only
concerned with file transfer over http (MTOM / WSE) so the encryption
overhead with https would be a factor. you're right, i didn't need session
state. i thought i needed it to preserve the auth cookie, but the two are
unrelated.

i don't see how the <authorization> element could help? granted i could
configure separate web service locations with different access rules,
although in my tests it was not possible to login to one web service
(login.asmx) and access another (MTOM.asmx) with the same ticket. do you
think this should be possible? taking the winforms client scenario, each
web service is its own proxy object, and it has no bearing on any other web
service proxy objects. perhaps they could share the same cookie containers,
i didn't get around to trying that.

any suggestions are most welcome, thanks again for the reply
tim
 
D

Dominick Baier

Hi,
yes, it is a hack, but a very useful one!
thanks for the suggestion, good idea to SSL, although my app is only
concerned with file transfer over http (MTOM / WSE) so the encryption
overhead with https would be a factor.

When you are already using WSE - why don't you simply implement your own
UsernameTokenManager?

SSL is in fact not really a big overhead - at least not for bandwidth - you
need more CPU cycle to do the encryption (in the worst case there are SSL
accelerator cards out there).

The authorization element can control access to individual files, directory
or the whole application. Have a look at the asp.net documentation.

If you want "single sign on" for different web services (== different client
proxies) you have to somehow share the authentication cookie between the
proxies.
 
S

Steven Cheng[MSFT]

Thanks for Dominick's informative suggestion.

Hi Tim,

I agree with Dominick. Although I haven't ever used forms authentication in
ASP.NET webservice, I think it is the same as you use httpwebrequest to
programamtically send request to forms authentication protected webpage.
And in webservice scenario, the client proxy just use the httpwebrequest
component and to make two proxies(accessing difference webservice endpoints
in the same ASP.NET application), you can consider share a cookie container
between them so that you only need to authentication against the server
once at the begining.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
T

Tim Mackey

hi Steven,
thanks for the tip. i actually tried using a WebClient implementation
first, sending a POST request to login.aspx which handled
Request.Form["Username"] etc in the Page_Load event. and this part of the
code worked fine, the values were passed in ok and the FormsAuthentication
code executed properly. i got stuck though when trying to use the web
service after executing the POST because there don't appaer to be any
cookies with the WebClient class. i have tried it again using the
HttpWebRequest class and now i can share the CookieContainers, it works
beautifully. just for future reference, here is what i have:

Login.aspx.cs
public partial class Log_in : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(Request["Username"] != null)
{
// web service trying to authenticate itself via HTTP request
if(FormsAuthentication.Authenticate(Request["Username"],
Request["Password"]))
FormsAuthentication.SetAuthCookie(Request["Username"], false);
}
}
}

Winforms client:
private bool AuthenticateWebService()
{
// send a HTTP web request to the login.aspx page, using the querystring to
pass in username and password
string postData = String.Format("?Username={0}&Password={1}",
this.txtUsername.Text, this.txtPassword.Text);
string url = this.fileTransferUpload1.WebService.Url.Replace("MTOM.asmx",
"") + "Login.aspx" + postData;
HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest;
req.CookieContainer = new CookieContainer();
HttpWebResponse response = (HttpWebResponse) req.GetResponse();

// copy the cookie container to the web services
this.WebService1.CookieContainer = req.CookieContainer;
this.WebService2.CookieContainer = req.CookieContainer;

return (response.Cookies.Count > 0); // true if there is a cookie, i.e.
authenticated successfully
}


thanks again for the suggestion
tim
 
T

Tim Mackey

hi dominick.
i finally got something going which is slightly less-of-a-hack, i posted it
in reply to steven's post.
i have a Custom UsernameTokenManager implementation from another project,
but i wanted to steer clear of it just as an experiment to see if a
reasonable solution could be done up just using Forms Auth. partly for
portability reasons too, this app could run with or without WSE very easily
and it would be nice to have a one-size fits all security set up that
integrates with the rest of the web site.

thanks again for all your help.
tim
 
D

Dominick Baier

Hi,

why don't you provide a "login.asmx" web service with no auth required -
which returns the encrypted ticket as a string - like:

string Login(string username, string password)
{
// create FormsAuthTicket
// encrypt ticket

return ticket;
}

(here is some code that shows how to create tickets:
http://www.leastprivilege.com/HowTo...msAuthenticationTicketsAndCustomUserData.aspx)




afterwards you use this ticket to set the cookiecontainer on your proxies??

again the <authorization> element would come in handy here, e.g.

<location path="login.asmx">
<system.web>
<authorization>
<allow users="*" />
<authorization>
<system.web>
</location>

<location path="service.asmx">
<system.web>
<authorization>
<deny users="?" />
<authorization>
<system.web>
</location>

You still need some logic to handle ticket expiration...


-----
Dominick Baier (http://www.leastprivilege.com)
hi Steven,
thanks for the tip. i actually tried using a WebClient implementation
first, sending a POST request to login.aspx which handled
Request.Form["Username"] etc in the Page_Load event. and this part of
the
code worked fine, the values were passed in ok and the
FormsAuthentication
code executed properly. i got stuck though when trying to use the web
service after executing the POST because there don't appaer to be any
cookies with the WebClient class. i have tried it again using the
HttpWebRequest class and now i can share the CookieContainers, it
works
beautifully. just for future reference, here is what i have:
Login.aspx.cs
public partial class Log_in : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(Request["Username"] != null)
{
// web service trying to authenticate itself via HTTP request
if(FormsAuthentication.Authenticate(Request["Username"],
Request["Password"]))
FormsAuthentication.SetAuthCookie(Request["Username"], false);
}
}
}
Winforms client:
private bool AuthenticateWebService()
{
// send a HTTP web request to the login.aspx page, using the
querystring to
pass in username and password
string postData = String.Format("?Username={0}&Password={1}",
this.txtUsername.Text, this.txtPassword.Text);
string url =
this.fileTransferUpload1.WebService.Url.Replace("MTOM.asmx",
"") + "Login.aspx" + postData;
HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest;
req.CookieContainer = new CookieContainer();
HttpWebResponse response = (HttpWebResponse) req.GetResponse();
// copy the cookie container to the web services
this.WebService1.CookieContainer = req.CookieContainer;
this.WebService2.CookieContainer = req.CookieContainer;
return (response.Cookies.Count > 0); // true if there is a cookie,
i.e.
authenticated successfully
}
thanks again for the suggestion
tim
Thanks for Dominick's informative suggestion.

Hi Tim,

I agree with Dominick. Although I haven't ever used forms
authentication
in
ASP.NET webservice, I think it is the same as you use httpwebrequest
to
programamtically send request to forms authentication protected
webpage.
And in webservice scenario, the client proxy just use the
httpwebrequest
component and to make two proxies(accessing difference webservice
endpoints
in the same ASP.NET application), you can consider share a cookie
container
between them so that you only need to authentication against the
server
once at the begining.
Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead

This posting is provided "AS IS" with no warranties, and confers no
rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,708
Latest member
SherleneF1

Latest Threads

Top