1
0
mirror of https://github.com/tomasvarg/OwinWebApiTest.git synced 2026-03-01 08:28:49 +00:00

Added CAS validation provider

This commit is contained in:
Tomas Varga 2018-01-09 05:59:25 +01:00
parent cf8f5edf0f
commit 099d1c2aa8
9 changed files with 187 additions and 33 deletions

View File

@ -1 +0,0 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="OwinWebApiTest.WebApiApplication" Language="C#" %>

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;
namespace OwinWebApiTest
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
}

View File

@ -0,0 +1,20 @@
namespace OwinWebApiTest.Models
{
public class CasServiceValidationResponse
{
public CasServiceValidationSuccess success { get; set; }
public CasServiceValidationFailure failure { get; set; }
}
public class CasServiceValidationSuccess
{
public string user { get; set; }
public string proxyGrantingTicket { get; set; }
}
public class CasServiceValidationFailure
{
public string code { get; set; }
public string description { get; set; }
}
}

View File

@ -138,22 +138,23 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Global.asax" /> <Content Include="Web.config">
<Content Include="Web.config" /> <SubType>Designer</SubType>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="App_Start\WebApiConfig.cs" /> <Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Controllers\ItemsController.cs" /> <Compile Include="Controllers\ItemsController.cs" />
<Compile Include="Global.asax.cs"> <Compile Include="Models\CasServiceValidationResponse.cs" />
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Models\Item.cs" /> <Compile Include="Models\Item.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Providers\CasAuthorizationServerProvider.cs" />
<Compile Include="Providers\SimpleAuthorizationServerProvider.cs" /> <Compile Include="Providers\SimpleAuthorizationServerProvider.cs" />
<Compile Include="Startup.cs" /> <Compile Include="Startup.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="packages.config" /> <Content Include="packages.config" />
<None Include="Properties\PublishProfiles\FileSystem.pubxml" />
<None Include="Web.Debug.config"> <None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon> <DependentUpon>Web.config</DependentUpon>
</None> </None>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>D:\devel\aspnet\OwinWebApiTest.deploy</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,116 @@
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin.Security;
using Microsoft.Owin.Infrastructure;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Configuration;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using OwinWebApiTest.Models;
namespace OwinWebApiTest.Providers
{
public class CasAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
private static string casValidationUrl;
private static string serviceUser;
public CasAuthorizationServerProvider()
{
casValidationUrl = ConfigurationManager.AppSettings["CasHost"]
+ ConfigurationManager.AppSettings["CasValidationPath"];
serviceUser = ConfigurationManager.AppSettings["ServiceUser"];
}
public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
// required but as we're not using client auth just validate & move on...
await Task.FromResult(context.Validated());
}
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
dynamic args = await context.Request.ReadFormAsync();
if (string.IsNullOrEmpty(args["ticket"]) || string.IsNullOrEmpty(args["service"])) {
context.SetError("invalid_grant", "No CAS ticket or service URL sent.");
context.Rejected();
return;
}
var res = await ValidateCasTicket(args["ticket"], args["service"]);
if (res.success == null && !string.IsNullOrEmpty(serviceUser)) {
res.success = new CasServiceValidationSuccess { user = serviceUser };
}
if (res.success == null) {
context.Rejected();
context.SetError("invalid_grant", "CAS validation failed: " + (res.failure != null
? res.failure.description : "No response received from the CAS server"));
return;
}
//var acda = new AccessControlDA();
//var ac = acda.GetAccessControl(res.success.user);
var ac = new { userId = args["username"], saveAllowed = true, saveAllUnits = true };
ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, res.success.user));
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
//identity.AddClaim(new Claim("user_name", context.UserName));
//identity.AddClaim(new Claim("sub", context.UserName));
// Identity info will be encoded into an Access ticket as a result of this call:
//context.Validated(identity);
var props = new AuthenticationProperties(new Dictionary<string, string> {
{ "username", res.success.user },
{ "AccessControl", JsonConvert.SerializeObject(ac) },
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
}
private async Task<CasServiceValidationResponse> ValidateCasTicket(string ticket, string service)
{
var requestUri = WebUtilities.AddQueryString(casValidationUrl, new Dictionary<string, string>() {
{ "service", service },
{ "ticket", ticket },
{ "format", "JSON" },
});
using (HttpClient client = new HttpClient())
{
return await GetCasServiceValidationAsync(client, requestUri);
}
}
public async Task<CasServiceValidationResponse> GetCasServiceValidationAsync(
HttpClient client, string requestUri)
{
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
dynamic resp = await response.Content.ReadAsAsync<JObject>();
var success = resp.SelectToken("serviceResponse.authenticationSuccess");
var failure = resp.SelectToken("serviceResponse.authenticationFailure");
return new CasServiceValidationResponse() {
success = success != null ? success.ToObject<CasServiceValidationSuccess>() : null,
failure = failure != null ? failure.ToObject<CasServiceValidationFailure>() : null,
};
}
}
}
}
}

View File

@ -8,12 +8,12 @@ namespace OwinWebApiTest.Providers
{ {
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{ {
context.Validated(); await Task.FromResult(context.Validated());
} }
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{ {
context.Validated(new ClaimsIdentity(context.Options.AuthenticationType)); await Task.FromResult(context.Validated(new ClaimsIdentity(context.Options.AuthenticationType)));
} }
} }

View File

@ -1,10 +1,12 @@
using System; using System;
using System.Configuration;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Owin;
using Owin; using Owin;
using System.Web.Http; using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Microsoft.Owin.Cors; using Microsoft.Owin.Cors;
using Microsoft.Owin.Security.OAuth;
using System.Web.Http;
using System.Net;
using OwinWebApiTest.Providers; using OwinWebApiTest.Providers;
@ -18,13 +20,17 @@ namespace OwinWebApiTest
{ {
app.UseCors(CorsOptions.AllowAll); app.UseCors(CorsOptions.AllowAll);
// token generation double tokenLifetime;
double.TryParse(ConfigurationManager.AppSettings["AccessTokenLifetimeHours"], out tokenLifetime);
// token configuration
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{ {
AllowInsecureHttp = true, AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"), TokenEndpointPath = new PathString("/api/auth/validate"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(8), AccessTokenExpireTimeSpan = TimeSpan.FromHours(tokenLifetime != 0 ? tokenLifetime : 10),
Provider = new SimpleAuthorizationServerProvider() //Provider = new SimpleAuthorizationServerProvider()
Provider = new CasAuthorizationServerProvider()
}); });
// token consumption // token consumption
@ -33,6 +39,9 @@ namespace OwinWebApiTest
HttpConfiguration config = new HttpConfiguration(); HttpConfiguration config = new HttpConfiguration();
app.UseWebApi(WebApiConfig.Register(config)); app.UseWebApi(WebApiConfig.Register(config));
// allow self-signed certificates
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
} }
} }
} }

View File

@ -8,7 +8,16 @@
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<appSettings></appSettings> <appSettings>
<add key="AppName" value="Owin WebApi Auth Test" />
<add key="AppVersion" value="0.1.0" />
<add key="CasHost" value="https://10.0.0.13:8443" />
<add key="CasValidationPath" value="/cas/serviceValidate" />
<add key="AccessTokenLifetimeHours" value="10" />
<!--
<add key="ServiceUser" value="vycepak" />
-->
</appSettings>
<system.web> <system.web>
<compilation debug="true" targetFramework="4.5.2" /> <compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" /> <httpRuntime targetFramework="4.5.2" />