using System;
using System.Linq;
using ServiceStack.Common;
using ServiceStack.Configuration;
using ServiceStack.Logging;
using ServiceStack.Text;
using ServiceStack.WebHost.Endpoints;
namespace ServiceStack.ServiceInterface.Auth
{
public class OAuthProvider : AuthProvider
{
public OAuthProvider() { }
public OAuthProvider(IResourceManager appSettings, string authRealm, string oAuthProvider)
: this(appSettings, authRealm, oAuthProvider, "ConsumerKey", "ConsumerSecret") { }
public OAuthProvider(IResourceManager appSettings, string authRealm, string oAuthProvider,
string consumerKeyName, string consumerSecretName)
{
this.AuthRealm = appSettings.Get("OAuthRealm", authRealm);
this.Provider = oAuthProvider;
this.RedirectUrl = appSettings.GetString("oauth.{0}.RedirectUrl".Fmt(oAuthProvider));
this.CallbackUrl = appSettings.GetString("oauth.{0}.CallbackUrl".Fmt(oAuthProvider));
this.ConsumerKey = appSettings.GetString("oauth.{0}.{1}".Fmt(oAuthProvider, consumerKeyName));
this.ConsumerSecret = appSettings.GetString("oauth.{0}.{1}".Fmt(oAuthProvider, consumerSecretName));
this.RequestTokenUrl = appSettings.Get("oauth.{0}.RequestTokenUrl", authRealm + "oauth/request_token");
this.AuthorizeUrl = appSettings.Get("oauth.{0}.AuthorizeUrl", authRealm + "oauth/authorize");
this.AccessTokenUrl = appSettings.Get("oauth.{0}.AccessTokenUrl", authRealm + "oauth/access_token");
this.OAuthUtils = new OAuthAuthorizer(this);
this.AuthHttpGateway = new AuthHttpGateway();
}
public IAuthHttpGateway AuthHttpGateway { get; set; }
public string ConsumerKey { get; set; }
public string ConsumerSecret { get; set; }
public string RequestTokenUrl { get; set; }
public string AuthorizeUrl { get; set; }
public string AccessTokenUrl { get; set; }
public OAuthAuthorizer OAuthUtils { get; set; }
public override bool IsAuthorized(IAuthSession session, IOAuthTokens tokens, Auth request = null)
{
if (request != null)
{
if (!LoginMatchesSession(session, request.UserName)) return false;
}
return tokens != null && !string.IsNullOrEmpty(tokens.AccessTokenSecret);
}
///
/// The entry point for all AuthProvider providers. Runs inside the AuthService so exceptions are treated normally.
/// Overridable so you can provide your own Auth implementation.
///
///
///
///
///
public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
{
var tokens = Init(authService, ref session, request);
//Default OAuth logic based on Twitter's OAuth workflow
if (!tokens.RequestToken.IsNullOrEmpty() && !request.oauth_token.IsNullOrEmpty())
{
OAuthUtils.RequestToken = tokens.RequestToken;
OAuthUtils.RequestTokenSecret = tokens.RequestTokenSecret;
OAuthUtils.AuthorizationToken = request.oauth_token;
OAuthUtils.AuthorizationVerifier = request.oauth_verifier;
if (OAuthUtils.AcquireAccessToken())
{
tokens.AccessToken = OAuthUtils.AccessToken;
tokens.AccessTokenSecret = OAuthUtils.AccessTokenSecret;
session.IsAuthenticated = true;
OnAuthenticated(authService, session, tokens, OAuthUtils.AuthInfo);
authService.SaveSession(session, SessionExpiry);
//Haz access!
return authService.Redirect(session.ReferrerUrl.AddHashParam("s", "1"));
}
//No Joy :(
tokens.RequestToken = null;
tokens.RequestTokenSecret = null;
authService.SaveSession(session, SessionExpiry);
return authService.Redirect(session.ReferrerUrl.AddHashParam("f", "AccessTokenFailed"));
}
if (OAuthUtils.AcquireRequestToken())
{
tokens.RequestToken = OAuthUtils.RequestToken;
tokens.RequestTokenSecret = OAuthUtils.RequestTokenSecret;
authService.SaveSession(session, SessionExpiry);
//Redirect to OAuth provider to approve access
return authService.Redirect(this.AuthorizeUrl
.AddQueryParam("oauth_token", tokens.RequestToken)
.AddQueryParam("oauth_callback", session.ReferrerUrl));
}
return authService.Redirect(session.ReferrerUrl.AddHashParam("f", "RequestTokenFailed"));
}
///
/// Sets the CallbackUrl and session.ReferrerUrl if not set and initializes the session tokens for this AuthProvider
///
///
///
///
///
protected IOAuthTokens Init(IServiceBase authService, ref IAuthSession session, Auth request)
{
if (request != null && !LoginMatchesSession(session, request.UserName))
{
//authService.RemoveSession();
//session = authService.GetSession();
}
var requestUri = authService.RequestContext.AbsoluteUri;
if (this.CallbackUrl.IsNullOrEmpty())
this.CallbackUrl = requestUri;
if (session.ReferrerUrl.IsNullOrEmpty())
session.ReferrerUrl = (request != null ? request.Continue : null)
?? authService.RequestContext.GetHeader("Referer");
if (session.ReferrerUrl.IsNullOrEmpty()
|| session.ReferrerUrl.IndexOf("/auth", StringComparison.OrdinalIgnoreCase) >= 0)
session.ReferrerUrl = this.RedirectUrl
?? ServiceStackHttpHandlerFactory.GetBaseUrl()
?? requestUri.Substring(0, requestUri.IndexOf("/", "https://".Length + 1));
var tokens = session.ProviderOAuthAccess.FirstOrDefault(x => x.Provider == Provider);
if (tokens == null)
session.ProviderOAuthAccess.Add(tokens = new OAuthTokens { Provider = Provider });
return tokens;
}
public virtual void LoadUserOAuthProvider(IAuthSession userSession, IOAuthTokens tokens) { }
}
}