About OpenIdDesktopClientOpenIdDesktopClient includes a set of services used to provide OpenID Authentication services to non-web applications. It utilizes OpenIdClient for authentication, resulting in full compatibility when extension plug-ins are needed. The end-user experience is seamless. The user is prompted for their OpenID, then a web browser opens at their workstation so they can authenticate with their provider. The authentication response is automatically received by the application, and the web browser is closed. After successful authentication, the application works normally. If you want to know more detail about the internals, see the "How it Works" section below for additional detail. Usage ExampleFirst, we need to initialize OpenIdDesktopClient, passing the OpenID we want to check, and (at minimum), the amount of time we want to wait before timing out. We can then register all the required extension plug-ins. The important piece is either subscribing to three important events, or calling RetrieveAuthenticationResponse(). RetrieveAuthenticationResponse() will block until a response is received, or the timeout has expired. If you prefer blocking to wait for the response, you can use the following example: using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using ExtremeSwank.OpenId;
using ExtremeSwank.OpenId.PlugIns.Extensions;
namespace MyProgram
{
public class Program
{
static void Main(string[] args)
{
OpenIdDesktopClient oidc = new OpenIdDesktopClient("extremeswank.com", 60);
// Optionally load an Extension plug-in if more functionality is needed
SimpleRegistration sr = new SimpleRegistration(oidc.Consumer);
sr.AddRequiredFields(SimpleRegistrationFields.FullName);
Uri url = oidc.BeginAuthentication();
if (url != null)
{
// Running Process.Start() here is useful for demonstration purposes only,
// as it will launch the default web browser wherever this code is running.
// In a client/server scenario, you will pass the value of "url" to the
// client, which should open a web browser locally.
Process.Start(url.AbsoluteUri);
// Wait until a response is received, and get whether or not
// authentication is successful
bool isValid = oidc.RetrieveAuthenticationResponse();
if (!isValid)
{
// Validation failed, get the current error condition.
Console.WriteLine("Validation failed!");
Console.WriteLine(oidc.Error);
}
else
{
// Validation succeeded, retrieve the OpenIDUser object
// and retrieve any requested extension data
Console.WriteLine("Validation succeeded!");
OpenIdUser user = oidc.Consumer.RetrieveUser();
Console.WriteLine(user.Identity);
Console.WriteLine(user.GetValue(SimpleRegistrationFields.FullName));
}
}
else
{
// Discovery of the OpenID failed. Either the user mistyped it,
// or a communication error occurred.
Console.WriteLine(oidc.Error);
}
Console.ReadLine();
}
}
}In the example below, the event method is used. This allows us to continue processing while we are waiting for a response. using System;
using System.Diagnostics;
using ExtremeSwank.OpenId;
using ExtremeSwank.OpenId.PlugIns.Extensions;
namespace MyProgram
{
class Program
{
static bool _DoneAuthenticating;
static bool _Debug = false;
static void Main(string[] args)
{
// If _Debug is set to true, listen for trace events and write
// them to the console.
if (_Debug)
{
Messenger m = new Messenger();
Trace.Listeners.Add(m);
}
// Write welcome message to the console
Console.WriteLine("Welcome to XXXX. Please log in.");
// Get the OpenIDConsumer
OpenIdDesktopClient oidc = GetOpenID();
// Get the redirect URL and start the temporary HTTP server
Uri url = oidc.BeginAuthentication();
if (url != null)
{
// Start the web browser local to this code.
// This should be done at the client in client/server apps.
Process.Start(url.AbsoluteUri);
}
else
{
// An error occurred
Console.WriteLine(oidc.Error);
_DoneAuthenticating = true;
}
InteractWithUser(oidc);
}
static OpenIdDesktopClient GetOpenID()
{
// Initialize the oidc variable
OpenIdDesktopClient oidc;
// We are going to prompt the user for their OpenID
// and check its validity. If its not valid,
// then repeat the process until a valid OpenID is
// entered.
while (true)
{
// Write the prompt to the console
Console.Write("OpenID: ");
// Get the user's response
string id = Console.ReadLine();
// If id is null, just loop through again without
// feedback.
if (!String.IsNullOrEmpty(id))
{
// Create a new OpenIDDesktopConsumer using the supplied ID,
// and a 60 second timeout. The rest of the options will
// be set to defaults.
oidc = new OpenIdDesktopClient(id, 60);
// Initialize a SimpleRegistration plugin
SimpleRegistration sr = new SimpleRegistration(oidc.Consumer);
sr.AddRequiredFields(SimpleRegistrationFields.FullName);
// Because we are doing this asynchronously, we need to listen for the
// events that could occur
oidc.AuthenticationSuccessful += new EventHandler(oidc_AuthenticationSuccessful);
oidc.AuthenticationResponseTimedOut += new EventHandler(oidc_AuthenticationResponseTimedOut);
oidc.AuthenticationFailed += new EventHandler(oidc_AuthenticationFailed);
// Do a discovery on the ID to confirm that its valid.
// If the ID is valid, return with the current OpenIDDesktopConsumer object.
if (oidc.Consumer.IsValidIdentity())
{
break;
}
// ID was not valid, loop through again
Console.WriteLine("Error Code: " + oidc.Error);
Console.WriteLine("Unable to discover OpenID. Please check your spelling and try again.");
}
}
return oidc;
}
static void InteractWithUser(OpenIdDesktopClient oidc)
{
// We want to keep the application running until a
// response has been received. We do this by
// continually waiting for user input.
while (true)
{
// Block until input has been entered
string c = Console.ReadLine();
// If a response has been received, or Timeout
// has occurred, it's safe to stop processing.
if (_DoneAuthenticating) { break; }
// If still waiting for the response and the
// user types "cancel", cancel everything
// and stop processing
if (c.ToLower() == "cancel")
{
oidc.CancelAuthentication();
break;
}
}
}
static void oidc_AuthenticationFailed(object sender, EventArgs e)
{
OpenIdDesktopClient oidc = (OpenIdDesktopClient)sender;
Console.WriteLine("Validation failed!");
Console.WriteLine(oidc.Error);
_DoneAuthenticating = true;
}
static void oidc_AuthenticationSuccessful(object sender, EventArgs e)
{
OpenIdDesktopClient oidc = (OpenIdDesktopClient)sender;
Console.WriteLine("Validation succeeded!");
OpenIdUser user = oidc.Consumer.RetrieveUser();
Console.WriteLine(user.Identity);
Console.WriteLine(user.GetValue(SimpleRegistrationFields.FullName));
_DoneAuthenticating = true;
}
static void oidc_AuthenticationResponseTimedOut(object sender, EventArgs e)
{
OpenIdDesktopClient oidc = (OpenIdDesktopClient)sender;
Console.WriteLine("Authentication response timed out!");
_DoneAuthenticating = true;
}
}
public class Messenger : TraceListener
{
public override void Write(string message)
{
Console.Write(message);
}
public override void WriteLine(string message)
{
Console.WriteLine(message);
}
}
}Stateless vs. Stateful ModeBy default, OpenIdDesktopClient works in Stateless mode. This reduces the complexity of your application by not saving any sort of state between authentication requests. If you have a large number of users using your application, and you expect to have many of them using the same OpenID Provider, Stateful authentication is a good idea. You have two options. For the default mode, use EnableStatefulMode(). For a more performant implementation, use EnableStatefulMode(assocmgr, sessionmgr). - The default Stateful mode will use in-memory volatile persistence objects that will be destroyed when OpenIdDesktopClient is disposed. This is useful for testing, or for situations where the usage of Stateful authentication requests are required, but the cached data does not need to be saved.
- The more performant method is to use ISessionPersistence and IAssociationPersistence objects to save your data in a permanent repository. Many built-in persistence objects make this very easy to implement into your own .NET compatible database. See the ExtremeSwank.OpenId.Persistence namespace for more information. If you are using some other form of persistence system, you can easily implement your own objects.
How it WorksWhen you initialize OpenIdDesktopClient, it initializes a copy of OpenIdClient, and sets up all the variables it needs. When oidc.BeginAuthentication() is called, a temporary HTTP server is loaded on a random port number between 1024 and 5000 (you can manually set this if needed), and the redirect URL for the web browser is returned. At this point, a web browser should be started wherever the user is located, which is completely up to you. This will allow the user to authenticate with their OpenID Provider. Upon authentication, the web browser will automatically redirect back to the temporary HTTP server, with the authentication response. Once received, the authentication response is verified. The application should then check RetrieveAuthenticationResponse() to see if the user is successfully authenticated. You can then retrieve the OpenIdUser object to get additional details and any requested extension data.
|
In a client/server environment, are all the examples above meant for the service side (where the return value of oidc.BeginAuthentication?(); are passed to the client) or are all examples client side?
grpmpk: In a client/server scenario, pass the URI from BeginAuthentication? to the client, and have the client open the web browser for authentication. Once authentication completes, the browser will redirect back to the temporary HTTP server running at your server.