I: using basicHttpBinding.
About Me
·
TransportWithMessageCredential uses means
message protection(Integrity, confidentiality) is provided at Transport level
but client authentication is done at Message-level.
·
TransportWithMssageCredential allows
Message-level authentication:
a)
UserName
authentication with all validators (Windows, Membership and custom).
b)
Windows
authentication both NTLM/Kerberos.
c)
Mutual
Certificate authentication.
·
This Recipe4.2.1,
uses UserName
authentication with Windows Validator
and
UseWindowsGroups (or UseAspNetRoles ) Validator for authorization.
Security Criteria
|
Client
Authentication
|
Windows
Validator against AD/WG clients.
|
Service Authentication
|
By SSL certificate Validating at
client-side.
|
Service Authorization / Impersonation
|
WindowsGroups
Validator / AspNetRoles Validator with respective Ado.net providers
|
Message Protection
|
SSL
/TLS (Transport Layer Security)
|
Transport / Binding
|
HTTP/
basicHttpBinding
|
Hosting / Interoperability
|
Self-Hosting / WCF interoperable.
|
IIS authentication
|
None
|
ASP.NET configuration
|
None
|
Step 1: Enable SSL and
configure IIS / Virtual directory.
·
SSL requires certificate to be
location=localMachine and store=My (i.e, Personal).
·
SSL certificate can be created
with(ChainTrust) or without RootCA(PeerTrust). Typically, SSL validated as
ChainTrust. Hence, use certificate with RootCA
·
RootCA is nothing but a
Certificate Authority that identifies all its issued certificates.
Step1.1: Create &
install SSL certificate at respective location.
1: Create self-signed Root CA with
private key.
sdkCmd>
makecert -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.cer
2: Install Root CA in Trusted Root
CA folder at both
(service/client) machines
OPEN MMC: StartèRunèEnter MMCèFileèAdd/Remove Snap-in èAddè
Add Standalone Snap-inè CertificatesèAdd èComputer Account (available to all users).
IMPORT RootCA: Right click on Trusted Root CA
folderèAll
TasksèImportèBrowse (path of .cer file)
3: Create and
install self-signed certificate for SSL as issued certificate.
sqlCmd>
makecert -sk yousufKey -iv RootCATest.pvk -n
"CN=homepc-9c7a749d" -ic RootCATest.cer -sr localmachine -ss my -sky
exchange -pe
Note: Don’t copy above command instead type
with same switch order. Because characters replace “-“ è
“–“ & " è “
Machine name = homepc-9c7a749d
(See MyComputerèPropertiesèComputerName tab)
Step1.2: Enable SSL over
IIS.
ASSIGN SSL
CERTIFICATE TO WEB-SITE(typically default Web-site):
StartèRunèInetMgr.msc; è Right click on default
web-siteèProperties
èDirectory
Services
èSecure Communication è Server Certificateè Next èAssign Exiting Certificate è www.MyDomain.Com
ENABLE SSL OVER Virtual.
Right
click on Login file/site èpropertiesè Directory servicesèSecure Communication
èEdit è Require Secure Channel(SSL)
Step1.3: Enable anonymous
Authentication over IIS
Right click on default web-site è properties èDirectory Services èAuthentication & Access Control è
Edit è Check in Enable Anonymous Access.
Step1.4: Reset IIS to update
changes; Start èRun
èReset
iis
Step 2: Create WCF
service with IIS hosting (Not in ASP.NET Development Server)
·
Create new
Web-site in location=HTTP location with
scheme= https;
Step 2.1. Create WCF Service:
VS è File è
New Website è WCF Service è
Location=HTTP; name= https://localhost/TransporCredentialOnlySecurity/
Step 2.2. Implement your Service:
[ServiceContract]
public interface IService
{
[OperationContract] string GetData1(int value);
[OperationContract] string
GetData2(int value);
}
public class Service : IService
{
public string GetData1(int value)
{ return "GetData1:" + value.ToString(); }
public string GetData2(int value) { return "GetData2:" +
value.ToString();}
}
Step 3: Configure WCF
for SSL (and then Test)
Step4: Work with Validators & Providers for Windows Clients
(Authentication/Authorization)
Step4.1: UserNameAuthenticationValidator
·
For
username authentication against Windows clients, WCF provides
predefined validator called Windows UserNamePasswordValidator.
·
Simply
use it by configuring userNamePasswordValidationMode="Windows" (see Step5)
Step4.2: AuthorizationValidator
·
For
username authorization use UseWindowsGroups or UseAspNetRoles" validator
along with
ADO.NET
Role provider either of:
a) System.Web.Security.WindowsTokenRoleProvider
/ AuthorizationStoreRoleProvider for
WorkGroup / ActiveDirectory Data Source respectively for role management.
//OR //
b) System.Web.Security.SqlRoleProvider
if you want to work with SQL data source by explicitly assign roles in db.
(a) : Working with WindowsTokenRoleProvider
/ AuthorizationStoreRoleProvider (for
WG/AD)
Enable Role Provider as
follows:
<system.web>
<roleManager enabled="true" defaultProvider="MyWindowsTokenRoleProvider">
<providers>
<clear />
<add name="MyWindowsTokenRoleProvider"
applicationName="MyAppName"
type="System.Web.Security.WindowsTokenRoleProvider,
System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</roleManager>
Note: Copy these settings form
Machine.config.comments then paste and edit it.
//OR//
(b): Working with SqlRoleProvider
Step-(b1): Create and Assign Roles to Windows
Accounts.
//Create
Role-provider database(default name=aspnetdb
otherwise use –d switch)
Sdkcmd> aspnet_regsql –S .\SQLExpress –E –A r //
- A r: Add only role-provider features; -E: Integrated Security.
// Open the database in Visual studio THEN
// Add new Role:
Execute sp aspnet_CreateRole ‘MyApplicationName’, ‘Managers’ // name should be
as in Providers.
// Assign user to role:
Execute sp aspnet-UsersInRoles_AddUsersToRoles ‘MyAppName’, “HOMEPC-9C7A749D\nayeem’
Step5: Configure the Service behavior to use Validators for
authentication and authorization.
<behaviors/serviceBehaviors>
<behavior
name="ServiceBehavior">
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Windows"
cacheLogonTokens="true"
cachedLogonTokenLifetime="00:01:00"
maxCachedLogonTokens="10"/>
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseWindowsGroups"
roleProviderName="MyWindowsTokenRoleProvider" />
<serviceMetadata
httpGetEnabled="false" httpsGetEnabled="True"/>
</behavior>
Step6: Implement the Client Application and Test Service with
valid/invalid credentials
·
Solution explorer èRight Click è Add new Website è”WCFTestClient”.
·
Add service reference; https:// homepc-9c7a749d/TransportWithMessageSecurity/; instead localhost use server name.
protected void
Page_Load(object sender, EventArgs e)
{
var proxy = new
ServiceReference1.ServiceClient();
//Provide windows credentials
proxy.ClientCredentials.UserName.UserName = "nayeem";
proxy.ClientCredentials.UserName.Password = "pass123";
Response.Output.Write("{0}",proxy.GetData1(123));
Response.Output.Write("{0}",proxy.GetData2(123));
proxy.Close();
}
Note(1) While adding service reference; no need to
enter client credentials. But while consuming service over proxy
credentials
needed.
(2)
No need of configuring as it is
required only for Message level security not for Transport security.
(3)
No need of certificate validation neither programmatically nor
declaratively e.g.,
/ . or handing System.Net.ServicePointManager.ServerCertificateValidationCallback
event
Step7: Grant
permissions on service operations with respective privileges to
clients/roles.(See Recipe4.2.1)
Use [PrincipalPermission(SecurityAction.Demand, Role="Admin")] over Operation contract
interface //OR //
if(!System.Threading.Thread.currentPrincipal.IsUnerInRole("Admin"))
throw new SecurityTokenValidationException("not Authorized"
);
Rebuild Service and execute host application. Execute
client application.
II: using wsHttpBinding.
About Me
·
TransportWithMessageCredential uses means message protection(Integrity,
confidentiality) is provided at Transport level but client authentication is
done at Message-level.
·
TransportWithMssageCredential allows
Message-level authentication:
Ø
UserName
authentication with all validators (Windows, Membership and custom).
Ø
Windows
authentication both NTLM/Kerberos.
Ø
Mutual
Certificate authentication.
·
This variation Recipe is same as Recipe 4.3.1,
but uses wsHttpBinding instead of basicHttpBinding.
·
wsHttpbinding needs some additional
requirements when working with TransportWithMessageCredential / Transport security.
1)
You
must have to configure http port with ssl certificate.
2) You must validate the ssl certificate at
client by handling
System.Net.ServicePointManager.ServerCertificateValidationCallback event.
Note: These are 2 additional
configurations are not required when binding is either basicHttpBinding /
netTcpBinding.
Step 1: Configure http
port with ssl certificate.
- SSL configuration
are required for WsHttpBinding + transport security+[Username
authentication | certificate authentication]
1.1: Get SSL certificate hash
§
StartèRunèenter
MMCèFileèAdd/Remove
snap-inèAddèCertificateèComputerAccountèFinish
§
Open Personal
certificate folder è Open installed ssl certificate.
§
Copy thumbprint
i.e, (certificate Hash) to a Text file è
Remove spaces è again copy it.(use it in next step)
1.2: Configure
HTTP for HTTPS
§
Use utility httpcfg.exe
(for Win2k3/Xp) / netsh.exe
(vista/Win2k8).
§
These utilities
are available as ServicePack support tools; and needs to be download explicitly.
For Win 2003 Server / XP
|
(a)
To bind SSL
certificate to a HTTP port number.
httpcfg set ssl -i 0.0.0.0:8005 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6
(b)
To
view/determine bind certificate when HTTP port.
httpcfg query ssl //or//
httpcfg query ssl>myMachinePorts.txt
(c)
To delete SSL
certificate form a port number
httpcfg delete ssl -i 0.0.0.0:8005 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6
|
For Win 2008 Server / Vista
|
(a)
To bind SSL
certificate to a HTTP port number.
netsh http add sslcert ipport=0.0.0.0:8005 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6
appid={00112233-4455-6677-8899-AABBCCDDEEFF}
Note: To generate appid ( VS èTools ècreate GUID èSelect registry format è Copy èExit.
(b)
To
view/determine bind certificate when HTTP port.
netsh http show sslcert
(c)
To delete SSL
certificate form a port number
netsh http delete sslcert ipport=0.0.0.0:8005
|
Step 2: Change binding(basicHttpBindingèWsHttpBinding) at
and elements.
2.1: <endpoint address="https://localhost:8005/service" binding="wsHttpBinding" contract="IService"
bindingConfiguration="wsEndpointBinding">
2.2: <bindings>/HttpBinding><binding name="basicEndpointBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None"/>
<message clientCredentialType="UserName"/>
</security>
Step 3: Validate the
ssl certificate at client side while consuming service:
using System.Security.Cryptography.X509Certificates; using System.Net; using System.Net.Security;
public partial class _Default : System.Web.UI.Page
{
protected
void Page_Load(object sender, EventArgs e)
{
ServicePointManager.ServerCertificateValidationCallback +=
new
System.Net.Security.RemoteCertificateValidationCallback(CertificateNoCheckHandler);
var proxy = new
ServiceReference1.ServiceClient();
proxy.ClientCredentials.UserName.UserName = "user1";
proxy.ClientCredentials.UserName.Password = "password#1";
Response.Output.Write("{0}",proxy.GetData1(123));
Response.Output.Write("{0}",proxy.GetData2(123));
proxy.Close();
}
public static bool
CertificateNoCheckHandler(object sender, X509Certificate certificate, X509Chain
chain, SslPolicyErrors sslPolicyErrors)
{ return true; }
}