Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

ASP.NET

...

has

...

two

...

authentication

...

models.

...

The

...

default

...

uses

...

your

...

existing

...

Windows

...

logon

...

and

...

IE

...

to

...

identify

...

you

...

to

...

the

...

Web

...

Server

...

without

...

any

...

interaction (although

...

this

...

also

...

applies

...

to

...

Basic

...

Authentication

...

where

...

the

...

Browser

...

pops

...

up

...

a

...

dialog

...

box).

...

The

...

other

...

approach

...

is

...

called

...

Forms

...

Authentication.

...

Microsoft

...

expects

...

an

...

application

...

using

...

this

...

technique

...

to

...

code

...

a

...

page

...

that

...

presents

...

a

...

Form

...

with

...

a

...

textbox

...

for

...

Userid

...

and

...

Password.

...

The

...

form

...

then

...

validates

...

the

...

two

...

fields

...

and

...

passes

...

the

...

authenticate

...

userid

...

back

...

to

...

the

...

.Net

...

Framework.

...

 In this

...

code

...

an

...

ASP.NET

...

page

...

is

...

created

...

that

...

claims

...

to

...

be

...

the

...

Forms

...

Authentication

...

page,

...

but

...

instead

...

of

...

asking

...

the

...

user

...

directly

...

for

...

Userid

...

and

...

Password

...

it

...

redirects

...

to

...

CAS,

...

validates

...

the

...

ticket,

...

and

...

then

...

passes

...

the

...

Userid

...

back

...

to

...

the

...

.NET

...

Framework.

...

Objectively,

...

.Net

...

doesn't

...

care

...

what

...

method

...

is

...

used

...

to

...

authenticate

...

the

...

user.

...

So

...

this

...

code

...

is

...

no

...

better

...

than

...

other

...

.NET

...

authentication

...

technologies,

...

and

...

in

...

some

...

cases

...

you

...

might

...

prefer

...

some

...

sort

...

of

...

filter

...

that

...

can

...

also

...

make

...

decisions.

...

This

...

code

...

is

...

provided

...

as

...

an

...

example

...

because

...

it

...

is

...

the

...

closest

...

match

...

in

...

spirit

...

and

...

design

...

between

...

the

...

CAS

...

service and any specific ASP.NET

...

authentication

...

model.

...

It

...

also

...

uses

...

the

...

best

...

documented

...

and

...

most

...

"application

...

developer"

...

oriented

...

programming

...

interface.

...

.NET

...

runs

...

in

...

an

...

environment

...

called

...

the

...

CLR

...

just

...

as

...

JSP

...

runs

...

in

...

a

...

JVM.

...

It

...

is

...

configured

...

by

...

a

...

Web.Config

...

file

...

in

...

the

...

directory

...

just

...

as

...

Servlets

...

are

...

configured

...

by

...

web.xml.

...

One

...

configuration

...

option

...

in

...

both

...

Web.Config

...

and

...

web.xml

...

is

...

how

...

the

...

pages

...

and

...

applications

...

in

...

the

...

directory

...

are

...

secured.

...

One

...

of

...

the

...

ASP.NET

...

options

...

is

...

to

...

use

...

"Forms

...

Authentication",

...

where

...

access

...

to

...

a

...

set

...

of

...

pages

...

requires

...

authentication

...

through

...

a

...

login

...

page.

...

Typically

...

a

...

Web.Config

...

is

...

generated

...

automatically

...

by

...

Visual

...

Studio.

...

Change

...

the

...

existing

...

authentication

...

to:

Code Block
xml
xml
<authentication mode="Forms" >
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  <forms name="casauth" loginUrl="login.aspx" />
&nbsp;&nbsp;&nbsp;
</authentication>
&nbsp;&nbsp;&nbsp; <authorization>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<authorization>
  <deny users="?" />
&nbsp;&nbsp;&nbsp;
</authorization>

This

...

tells

...

ASP.NET

...

to

...

require

...

authentication

...

for

...

all

...

access

...

to

...

the

...

directory

...

and

...

to

...

internally

...

reroute

...

every

...

unauthenticated

...

user

...

to

...

the

...

login.aspx

...

page.

...

You

...

can

...

read

...

the

...

Microsoft

...

documentation

...

if

...

you

...

want

...

a

...

more

...

limited

...

scope

...

of

...

protection.

...

Now

...

in

...

Visual

...

Studio

...

create

...

a

...

login.aspx

...

page

...

with

...

CS

...

as

...

the

...

language.

...

I

...

suggest

...

dragging

...

a

...

Label

...

object

...

to

...

it

...

from

...

the

...

Toolbox,

...

which

...

will

...

become

...

Label1

...

and

...

will

...

be

...

used

...

for

...

an

...

error

...

message

...

if

...

something

...

goes

...

wrong.

...

There

...

is

...

nothing

...

more

...

on

...

the

...

"login

...

web

...

page".

...

The

...

rest

...

is

...

done

...

with

...

code.

...

In

...

the generated login.aspx.cs

...

file,

...

add

...

System.IO,

...

System.Net,

...

System.Web,

...

and

...

System.Xml

...

to

...

the

...

list

...

of

...

using

...

statements

...

(imports

...

for

...

you

...

Java

...

folk).

...

The

...

rest

...

is

...

to

...

code

...

a

...

Page_Load

...

event

...

handler.

...

You

...

can

...

probably

...

improve

...

on:

...

Code Block
// Local specific CAS host
&nbsp;&nbsp;&nbsp;
private const string CASHOST = "https://secure.its.yale.edu/cas/";
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
// After the page has been loaded, this routine is called.
&nbsp;&nbsp;&nbsp;
protected void Page_Load(object sender, EventArgs e)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
  // Look for the "ticket=" after the "?" in the URL
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  string tkt = *Request.QueryString\[CAS:"ticket"\];*

 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // This page is the CAS service=, but discard any query string residue
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  string service = Request.Url.GetLeftPart(UriPartial.Path);

 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // First time through there is no ticket=, so redirect to CAS login
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  if (tkt == null \|\| tkt.Length == 0)
  {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    string redir = CASHOST + "login?" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      "service=" + service;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *
    Response.Redirect(redir);*
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  // Second time (back from CAS) there is a ticket= to validate
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  string validateurl = CASHOST + "serviceValidate?" +
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    "ticket=" + tkt + "&"\+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    "service=" + service;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  StreamReader Reader = new StreamReader( new WebClient().OpenRead(validateurl));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  string resp = Reader.ReadToEnd();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  // I like to have the text in memory for debugging rather than parsing the stream

 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Some boilerplate to set up the parse.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  NameTable nt = new NameTable();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  XmlTextReader reader = new XmlTextReader(resp, XmlNodeType.Element, context);

 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string netid = null;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  // A very dumb use of XML. Just scan for the "user". If it isn't there, its an error.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  while (reader.Read())
 {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
    if (reader.IsStartElement()) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      string tag = reader.LocalName;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      if (tag=="user")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        netid = reader.ReadString();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    }
  }
  // if you want to parse the proxy chain, just add the logic above
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  reader.Close();
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // If there was a problem, leave the message on the screen. Otherwise, return to original page.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  if (netid == null)
  {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    Label1.Text = "CAS returned to this application, but then refused to validate your identity.";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  }
  else
  {
    Label1.Text = "Welcome " + netid;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *    FormsAuthentication.RedirectFromLoginPage(netid*, false); // set netid in ASP.NET blocks
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;
  }
}

Now

...

in

...

any

...

page

...

in

...

the

...

application,

...

the

...

netid

...

is

...

accessible

...

as

...

Context.User.Identity.Name.

For an alternative code sample that also implements a Role Provider see ASP.NET Forms Authentication with Role Provider.

Another alternative code sample based on this tutorial that supports Single Sign Out with sample app is available here.