View of /trunk/AssetServer/Extensions/OpenIdAuth.cs
Parent Directory
|
Revision Log
Revision 73 -
(download)
(annotate)
Thu Feb 5 08:12:58 2009 UTC (4 years, 3 months ago) by jhurliman
File size: 12661 byte(s)
Thu Feb 5 08:12:58 2009 UTC (4 years, 3 months ago) by jhurliman
File size: 12661 byte(s)
* Added web OpenID auth path back in * Added the AuthorizeWhitelist extension to whitelist access based on OpenID identities * Continued work on the GridServer
/*
* Copyright (c) 2008 Intel Corporation
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* -- Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* -- Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* -- Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using DotNetOpenId;
using DotNetOpenId.RelyingParty;
using ExtensionLoader;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using HttpServer;
public struct UserAuthentication
{
public IAuthenticationResponse OpenIdResponse;
public UUID Token;
}
namespace AssetServer.Extensions
{
public class OpenIdAuth : IExtension<AssetServer>, IAuthenticationProvider
{
const string HTML_HEADER = "<html><head><title>Asset Server Authentication</title></head><body>";
const string HTML_FOOTER = "</body></html>";
const string AUTH_FORM = "<form method=\"post\"><label for=\"openid_identifier\">OpenID URL:</label> <input type=\"text\" name=\"openid_identifier\" id=\"openid_identifier\"/> <input type=\"submit\" value=\"Authenticate\"></form>";
AssetServer server;
ApplicationMemoryStore openidStore = new ApplicationMemoryStore();
DoubleDictionary<UUID, Uri, Uri> authStore = new DoubleDictionary<UUID, Uri, Uri>();
public OpenIdAuth()
{
}
public void Start(AssetServer server)
{
this.server = server;
server.HttpServer.AddHandler("get", null, @"^/authenticate", WebGetHandler);
server.HttpServer.AddHandler("post", "application/x-www-form-urlencoded", @"^/authenticate", WebAuthHandler);
server.HttpServer.AddHandler("post", "application/json", @"^/authenticate", AuthStartHandler);
server.HttpServer.AddHandler(null, null, @"^/authenticate", AuthHandler);
}
public void Stop()
{
}
public void AddIdentifier(UUID token, Uri identifier)
{
lock (authStore)
{
// If this token already existed in the store, remove it first
if (authStore.ContainsKey(token))
{
authStore.Remove(token, authStore[token]);
}
// We only support one session per identifier, so check if this
// identifier has another session open and remove it
else if (authStore.ContainsKey(identifier))
{
Logger.Log.Warn("[OpenIdAuth] Executing slow remove query for existing session, identifier: " +
identifier.ToString());
authStore.Remove(identifier);
}
authStore.Add(token, identifier, identifier);
}
}
public bool RemoveIdentifier(UUID token)
{
lock (authStore)
{
Uri identifier;
if (authStore.TryGetValue(token, out identifier))
return authStore.Remove(token, identifier);
else
return false;
}
}
public bool TryGetIdentifier(UUID token, out Uri identifier)
{
lock (authStore)
return authStore.TryGetValue(token, out identifier);
}
bool AuthStartHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
{
try
{
OSDMap map = OSDParser.DeserializeJson(request.Body) as OSDMap;
Uri claimedIdentifier = map["identifier"].AsUri();
if (claimedIdentifier != null)
{
OpenIdRelyingParty rp = new OpenIdRelyingParty(openidStore, null, null);
string baseURL = String.Format("{0}://{1}", request.Uri.Scheme, request.Uri.Authority);
Realm realm = new Realm(baseURL);
IAuthenticationRequest authRequest = rp.CreateRequest(claimedIdentifier, realm, request.Uri);
response.Status = authRequest.RedirectingResponse.Code;
for (int i = 0; i < authRequest.RedirectingResponse.Headers.AllKeys.Length; i++)
{
string key = authRequest.RedirectingResponse.Headers.AllKeys[i];
response.AddHeader(key, authRequest.RedirectingResponse.Headers[key]);
}
}
else
{
response.Status = HttpStatusCode.BadRequest;
}
}
catch (Exception ex)
{
Logger.Log.Warn(ex.Message);
response.Status = HttpStatusCode.InternalServerError;
response.Reason = ex.Message;
}
return true;
}
bool AuthHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
{
UUID authToken = UUID.Zero;
if (!String.IsNullOrEmpty(request.Uri.Query))
{
NameValueCollection query = HttpUtility.ParseQueryString(request.Uri.Query);
OpenIdRelyingParty rp = new OpenIdRelyingParty(openidStore, request.Uri, query);
if (rp.Response != null)
{
if (rp.Response.Status == AuthenticationStatus.Authenticated)
{
authToken = UUID.Random();
AddIdentifier(authToken, new Uri(rp.Response.ClaimedIdentifier.ToString()));
response.Cookies.Add(new ResponseCookie("authToken", authToken.ToString(), DateTime.Now + TimeSpan.FromDays(7)));
}
else if (rp.Response.Exception != null)
{
response.Reason = rp.Response.Exception.Message;
}
}
}
else
{
authToken = Utils.GetAuthToken(request);
}
Uri identifier;
if (authToken != UUID.Zero && server.AuthenticationProvider.TryGetIdentifier(authToken, out identifier))
{
OSDMap osd = new OSDMap(2);
osd.Add("identifier", OSD.FromUri(identifier));
osd.Add("auth_token", OSD.FromUUID(authToken));
byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJson(osd).ToJson());
response.ContentLength = responseData.Length;
response.ContentType = "application/json";
response.Body.Write(responseData, 0, responseData.Length);
response.Body.Flush();
}
else
{
// Default response
response.Status = HttpStatusCode.Forbidden;
}
return true;
}
bool WebGetHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
{
const string HTML_HEADER = "<html><head><title>Asset Server Authentication</title></head><body>";
const string HTML_FOOTER = "</body></html>";
const string AUTH_FORM = "<form method=\"post\"><label for=\"openid_identifier\">OpenID URL:</label> <input type=\"text\" name=\"openid_identifier\" id=\"openid_identifier\"/> <input type=\"submit\" value=\"Authenticate\"></form>";
if (!String.IsNullOrEmpty(request.Uri.Query))
{
NameValueCollection query = HttpUtility.ParseQueryString(request.Uri.Query);
OpenIdRelyingParty rp = new OpenIdRelyingParty(openidStore, request.Uri, query);
if (rp.Response != null && rp.Response.Status == AuthenticationStatus.Authenticated)
{
UUID token = UUID.Random();
AddIdentifier(token, new Uri(rp.Response.ClaimedIdentifier.ToString()));
response.Cookies.Add(new ResponseCookie("authToken", token.ToString(), DateTime.Now + TimeSpan.FromDays(7)));
}
response.Status = HttpStatusCode.Redirect;
response.AddHeader("Location", String.Format("{0}://{1}{2}", request.Uri.Scheme, request.Uri.Authority, request.Uri.AbsolutePath));
}
else
{
UUID token;
Uri identifier;
RequestCookie authCookie = request.Cookies != null ? request.Cookies["authToken"] : null;
if (authCookie != null && UUID.TryParse(authCookie.Value, out token) && authStore.TryGetValue(token, out identifier))
{
string responseStr = String.Format("{0}Authenticated as {1}, token is {2}{3}",
HTML_HEADER, identifier, token, HTML_FOOTER);
byte[] data = Encoding.UTF8.GetBytes(responseStr);
response.Body.Write(data, 0, data.Length);
}
else
{
string responseStr = HTML_HEADER + AUTH_FORM + HTML_FOOTER;
byte[] data = Encoding.UTF8.GetBytes(responseStr);
response.Body.Write(data, 0, data.Length);
}
}
return true;
}
bool WebAuthHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
{
byte[] buffer = new byte[request.ContentLength];
int pos = 0;
while (pos < buffer.Length)
pos += request.Body.Read(buffer, 0, buffer.Length);
string queryString = HttpUtility.UrlDecode(buffer, Encoding.UTF8);
NameValueCollection query = System.Web.HttpUtility.ParseQueryString(queryString);
string[] openidIdentifiers = query.GetValues("openid_identifier");
if (openidIdentifiers.Length == 1)
{
Identifier identifier;
if (UriIdentifier.TryParse(openidIdentifiers[0], out identifier))
{
OpenIdRelyingParty rp = new OpenIdRelyingParty(openidStore, null, null);
string baseURL = String.Format("{0}://{1}", request.Uri.Scheme, request.Uri.Authority);
Realm realm = new Realm(baseURL);
IAuthenticationRequest authRequest = rp.CreateRequest(identifier, realm, request.Uri);
response.Status = authRequest.RedirectingResponse.Code;
for (int i = 0; i < authRequest.RedirectingResponse.Headers.Keys.Count; i++)
{
string key = authRequest.RedirectingResponse.Headers.Keys[i];
response.AddHeader(key, authRequest.RedirectingResponse.Headers[key]);
}
}
}
return true;
}
}
}
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

