Removed IdentityServer, it was overkill #865

This commit is contained in:
Jamie.Rees 2017-08-07 11:57:15 +01:00
parent 7645aff996
commit 046211e017
17 changed files with 226 additions and 346 deletions

View file

@ -7,14 +7,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.IdentityResolver;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;

View file

@ -1,53 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Ombi.Store.Entities;
namespace Ombi.Core.IdentityResolver
{
public class OmbiProfileService : IProfileService
{
public OmbiProfileService(UserManager<OmbiUser> um)
{
UserManager = um;
}
private UserManager<OmbiUser> UserManager { get; }
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
if (context.RequestedClaimTypes.Any())
{
var user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == context.Subject.GetSubjectId());
if (user != null)
{
var roles = await UserManager.GetRolesAsync(user);
var claims = new List<Claim>
{
new Claim(JwtClaimTypes.Name, user.UserName)
};
foreach (var role in roles)
{
claims.Add(new Claim(JwtClaimTypes.Role, role));
}
context.AddFilteredClaims(claims);
context.IssuedClaims.AddRange(claims);
}
}
}
public Task IsActiveAsync(IsActiveContext context)
{
return Task.FromResult(0);
}
}
}

View file

@ -1,156 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Api.Emby;
using Ombi.Api.Emby.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
namespace Ombi.Core.IdentityResolver
{
public class OmbiOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public OmbiOwnerPasswordValidator(UserManager<OmbiUser> um, IPlexApi plexApi, IEmbyApi embyApi,
ISettingsService<PlexSettings> settings, ISettingsService<OmbiSettings> ombiSettings,
ISettingsService<EmbySettings> embySettings, IAuditRepository log)
{
UserManager = um;
PlexApi = plexApi;
PlexSettings = settings;
OmbiSettings = ombiSettings;
EmbyApi = embyApi;
EmbySettings = embySettings;
Audit = log;
}
private UserManager<OmbiUser> UserManager { get; }
private IPlexApi PlexApi { get; }
private IEmbyApi EmbyApi{ get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private ISettingsService<OmbiSettings> OmbiSettings { get; }
private IAuditRepository Audit { get; }
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
await Audit.Record(AuditType.None, AuditArea.Authentication, $"User {context.UserName} attempted to login", context.UserName);
var users = UserManager.Users;
if (await LocalUser(context, users))
{
return;
}
var ombi = await OmbiSettings.GetSettingsAsync();
if (ombi.AllowExternalUsersToAuthenticate)
{
if (await PlexUser(context, users))
{
return;
}
if (await EmbyUser(context, users))
{
return;
}
}
await Audit.Record(AuditType.Fail, AuditArea.Authentication, $"User {context.UserName} failed to login", context.UserName);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Username or password is incorrect");
}
private async Task<bool> PlexUser(ResourceOwnerPasswordValidationContext context, IQueryable<OmbiUser> users)
{
var signInResult = await PlexApi.SignIn(new UserRequest {login = context.UserName, password = context.Password});
if (signInResult?.user == null)
{
return false;
}
// Do we have a local user?
return await GetUserDetails(context, users, UserType.PlexUser);
}
private async Task<bool> EmbyUser(ResourceOwnerPasswordValidationContext context, IQueryable<OmbiUser> users)
{
var embySettings = await EmbySettings.GetSettingsAsync();
var signInResult = await EmbyApi.LogIn(context.UserName, context.Password, embySettings.ApiKey,
embySettings.FullUri);
if (string.IsNullOrEmpty(signInResult?.Name))
{
return false;
}
return await GetUserDetails(context, users, UserType.EmbyUser);
}
private async Task<bool> GetUserDetails(ResourceOwnerPasswordValidationContext context, IQueryable<OmbiUser> users, UserType userType)
{
var user = await users.FirstOrDefaultAsync(x => x.UserName == context.UserName && x.UserType == userType);
if (user != null)
{
var roles = await UserManager.GetRolesAsync(user);
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName)
};
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
context.Result = new GrantValidationResult(user.UserName, "password", claims);
return true;
}
// Create the user?
return true;
}
public async Task<bool> LocalUser(ResourceOwnerPasswordValidationContext context, IQueryable<OmbiUser> users)
{
var user = await users.FirstOrDefaultAsync(x => x.UserName == context.UserName && x.UserType == UserType.LocalUser);
if (user == null)
{
return false;
}
var passwordValid = await UserManager.CheckPasswordAsync(user, context.Password);
if (!passwordValid)
{
await Audit.Record(AuditType.Fail, AuditArea.Authentication, $"User {context.UserName} failed to login", context.UserName);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Username or password is incorrect");
return true;
}
var roles = await UserManager.GetRolesAsync(user);
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName)
};
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
context.Result = new GrantValidationResult(user.UserName, "password", claims);
await Audit.Record(AuditType.Success, AuditArea.Authentication, $"User {context.UserName} has logged in", context.UserName);
return true;
}
}
}

View file

@ -9,7 +9,6 @@
<PackageReference Include="AutoMapper" Version="6.1.0" /> <PackageReference Include="AutoMapper" Version="6.1.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="2.0.1" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="2.0.1" />
<PackageReference Include="Hangfire" Version="1.6.14" /> <PackageReference Include="Hangfire" Version="1.6.14" />
<PackageReference Include="IdentityServer4" Version="1.5.2" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="1.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.2" />

View file

@ -14,7 +14,6 @@ using Ombi.Api.TvMaze;
using Ombi.Core; using Ombi.Core;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.IdentityResolver;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Core.Rule; using Ombi.Core.Rule;

View file

@ -7,28 +7,21 @@ import { IUserLogin, ILocalUser } from './IUserLogin';
import { tokenNotExpired, JwtHelper } from 'angular2-jwt'; import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
import { Http, Headers, URLSearchParams } from '@angular/http'; import { Http, Headers } from '@angular/http';
@Injectable() @Injectable()
export class AuthService extends ServiceHelpers { export class AuthService extends ServiceHelpers {
constructor(http: Http) { constructor(http: Http) {
super(http, '/connect/token'); super(http, '/api/v1/token');
} }
jwtHelper: JwtHelper = new JwtHelper(); jwtHelper: JwtHelper = new JwtHelper();
login(login: IUserLogin): Observable<any> { login(login: IUserLogin): Observable<any> {
this.headers = new Headers(); this.headers = new Headers();
this.headers.append('Content-Type', 'application/x-www-form-urlencoded'); this.headers.append('Content-Type', 'application/json');
let data = new URLSearchParams();
data.append('client_id', 'frontend');
data.append('scope', 'api');
data.append('client_secret', 'secret');
data.append('grant_type', 'password');
data.append('username', login.username);
data.append('password', login.password);
return this.http.post(`${this.url}/`, data.toString(), { headers: this.headers }) return this.http.post(`${this.url}/`, JSON.stringify(login), { headers: this.headers })
.map(this.extractData); .map(this.extractData);
} }

View file

@ -1,4 +1,8 @@
 
<img class="landing-header" src="/images/logo.png" width="300" />
<div class="landing-block shadow">
<div class="media">
<div id="contentBody" class="media-body">
<h4 class="media-heading landing-title">Create the Admin account</h4> <h4 class="media-heading landing-title">Create the Admin account</h4>
<small>This account will be used to configure your settings and also manage all of the requests. Note: this should not be the same as your Plex/Emby account (you can change this later in the User Management Settings)</small> <small>This account will be used to configure your settings and also manage all of the requests. Note: this should not be the same as your Plex/Emby account (you can change this later in the User Management Settings)</small>
<div class="form-group"> <div class="form-group">
@ -18,3 +22,6 @@
<button (click)="createUser()" type="submit" class="btn btn-success-outline">Finish</button> <button (click)="createUser()" type="submit" class="btn btn-success-outline">Finish</button>
</div> </div>
</div> </div>
</div>
</div>
</div>

View file

@ -1,4 +1,8 @@
 
<img class="landing-header" src="/images/logo.png" width="300" />
<div class="landing-block shadow">
<div class="media">
<div id="contentBody" class="media-body">
<h4 class="media-heading landing-title">Emby Authentication</h4> <h4 class="media-heading landing-title">Emby Authentication</h4>
<div *ngIf="embySettings"> <div *ngIf="embySettings">
<div class="form-group"> <div class="form-group">
@ -30,3 +34,6 @@
<a (click)="save()" id="embyApiKeySave" class="btn btn-primary-outline">Next <div id="spinner"></div></a> <a (click)="save()" id="embyApiKeySave" class="btn btn-primary-outline">Next <div id="spinner"></div></a>
</div> </div>
</div> </div>
</div>
</div>
</div>

View file

@ -1,21 +1,29 @@
 <div> 
<h4 class="media-heading landing-title wizard-heading" id="statusTitle">Please choose your media server</h4> <img class="landing-header" src="/images/logo.png" width="300" />
<div class="form-group"> <div class="landing-block shadow">
<div class="row"> <div class="media">
<a (click)="emby()" id="embyImg"> <div id="contentBody" class="media-body">
<img class="wizard-img" src="/images/emby-logo-dark.jpg" /> <h4 class="media-heading landing-title wizard-heading" id="statusTitle">Please choose your media server</h4>
</a> <div class="form-group">
</div> <div class="row">
<div class="row"> <a (click)="emby()" id="embyImg">
<a (click)="plex()" id="plexImg"> <img class="wizard-img" src="/images/emby-logo-dark.jpg" />
<img class="wizard-img" src="/images/plex-logo-reversed.png" /> </a>
</a> </div>
</div> <div class="row">
<div class="row"> <a (click)="plex()" id="plexImg">
<button (click)="skip()" class="btn btn-primary-outline wizard-img" id="plexImg"> <img class="wizard-img" src="/images/plex-logo-reversed.png" />
Skip </a>
</button> </div>
</div> <div class="row">
<button (click)="skip()" class="btn btn-primary-outline wizard-img" id="plexImg">
Skip
</button>
</div>
</div> </div>
</div>
</div>
</div> </div>

View file

@ -3,7 +3,6 @@ import { Router } from '@angular/router';
@Component({ @Component({
templateUrl: './mediaserver.component.html', templateUrl: './mediaserver.component.html',
}) })
export class MediaServerComponent { export class MediaServerComponent {
@ -19,8 +18,7 @@ export class MediaServerComponent {
this.router.navigate(['Wizard/Emby']); this.router.navigate(['Wizard/Emby']);
} }
skip() skip() {
{
this.router.navigate(['Wizard/CreateAdmin']); this.router.navigate(['Wizard/CreateAdmin']);
} }
} }

View file

@ -1,4 +1,9 @@
<h4 class="media-heading landing-title">Plex Authentication</h4> 
<img class="landing-header" src="/images/logo.png" width="300" />
<div class="landing-block shadow">
<div class="media">
<div id="contentBody" class="media-body">
<h4 class="media-heading landing-title">Plex Authentication</h4>
<div class="form-group"> <div class="form-group">
<label for="username" class="control-label">Username and Password</label> <label for="username" class="control-label">Username and Password</label>
<div> <div>
@ -15,3 +20,6 @@
<button (click)="requestAuthToken()" class="btn btn-primary-outline">Request Token <i class="fa fa-key"></i></button> <button (click)="requestAuthToken()" class="btn btn-primary-outline">Request Token <i class="fa fa-key"></i></button>
</div> </div>
</div> </div>
</div>
</div>
</div>

View file

@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Ombi.Models;
using Ombi.Models.Identity;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
namespace Ombi.Controllers
{
[ApiV1]
public class TokenController
{
public TokenController(UserManager<OmbiUser> um, IOptions<TokenAuthentication> ta,
IApplicationConfigRepository config)
{
UserManager = um;
TokenAuthenticationOptions = ta.Value;
Config = config;
}
private TokenAuthentication TokenAuthenticationOptions { get; }
private IApplicationConfigRepository Config { get; }
private UserManager<OmbiUser> UserManager { get; }
/// <summary>
/// Gets the token.
/// </summary>
/// <param name="model">The model.</param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
{
var user = await UserManager.FindByNameAsync(model.Username);
if (user == null)
{
return null;
}
// Verify Password
if ((await UserManager.CheckPasswordAsync(user, model.Password)))
{
// Get the url
var url = Config.Get(ConfigurationTypes.Url);
var port = Config.Get(ConfigurationTypes.Port);
#if !DEBUG
var audience = $"{url}:{port}";
#else
var audience = $"http://localhost:52038/";
#endif
var roles = await UserManager.GetRolesAsync(user);
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim("name", user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
claims.AddRange(roles.Select(role => new Claim("role", role)));
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenAuthenticationOptions.SecretKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.UtcNow.AddHours(5),
signingCredentials: creds,
audience: "Ombi", issuer:"Ombi"
);
return new JsonResult(new
{
access_token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return null;
}
/// <summary>
/// Refreshes the token.
/// </summary>
/// <param name="model">The model.</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[HttpPost("refresh")]
public async Task<IActionResult> RefreshToken([FromBody] UserAuthModel model)
{
throw new NotImplementedException();
}
}
}

View file

@ -1,59 +0,0 @@
using System.Collections.Generic;
using IdentityModel;
using IdentityServer4.Models;
namespace Ombi
{
public class IdentityConfig
{
// scopes define the resources in your system
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource {
Name = "role",
UserClaims = new List<string> {"role"}
}
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api", "API")
{
UserClaims = {JwtClaimTypes.Name, JwtClaimTypes.Role, JwtClaimTypes.Email, JwtClaimTypes.Id},
}
};
}
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
// client credentials client
return new List<Client>
{
new Client
{
ClientId = "frontend",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256()) // TODO read up on what this actually is
},
AllowedScopes =
{
"api",
},
AccessTokenType = AccessTokenType.Jwt
}
};
}
}
}

View file

@ -0,0 +1,7 @@
namespace Ombi.Models.Identity
{
public class TokenAuthentication
{
public string SecretKey { get; set; }
}
}

View file

@ -43,9 +43,6 @@
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" /> <PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" /> <PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
<PackageReference Include="Hangfire.SQLite.Core" Version="1.0.2" /> <PackageReference Include="Hangfire.SQLite.Core" Version="1.0.2" />
<PackageReference Include="IdentityServer4" Version="1.5.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" /> <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.2" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />

View file

@ -2,16 +2,13 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Text;
using AutoMapper; using AutoMapper;
using AutoMapper.EquivalencyExpression; using AutoMapper.EquivalencyExpression;
using Hangfire; using Hangfire;
using Hangfire.MemoryStorage; using Hangfire.MemoryStorage;
using Hangfire.SQLite;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.SpaServices.Webpack; using Microsoft.AspNetCore.SpaServices.Webpack;
@ -25,10 +22,10 @@ using Microsoft.Extensions.Options;
using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Ombi.Config; using Ombi.Config;
using Ombi.Core.IdentityResolver;
using Ombi.DependencyInjection; using Ombi.DependencyInjection;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Mapping; using Ombi.Mapping;
using Ombi.Models.Identity;
using Ombi.Schedule; using Ombi.Schedule;
using Ombi.Store.Context; using Ombi.Store.Context;
using Ombi.Store.Entities; using Ombi.Store.Entities;
@ -83,15 +80,16 @@ namespace Ombi
.AddEntityFrameworkStores<OmbiContext>() .AddEntityFrameworkStores<OmbiContext>()
.AddDefaultTokenProviders(); .AddDefaultTokenProviders();
services.AddIdentityServer()
.AddTemporarySigningCredential() //services.AddIdentityServer()
.AddInMemoryPersistedGrants() // .AddTemporarySigningCredential()
.AddInMemoryIdentityResources(IdentityConfig.GetIdentityResources()) // .AddInMemoryPersistedGrants()
.AddInMemoryApiResources(IdentityConfig.GetApiResources()) // .AddInMemoryIdentityResources(IdentityConfig.GetIdentityResources())
.AddInMemoryClients(IdentityConfig.GetClients()) // .AddInMemoryApiResources(IdentityConfig.GetApiResources())
.AddAspNetIdentity<OmbiUser>() // .AddInMemoryClients(IdentityConfig.GetClients())
.Services.AddTransient<IResourceOwnerPasswordValidator, OmbiOwnerPasswordValidator>() // .AddAspNetIdentity<OmbiUser>()
.AddTransient<IProfileService, OmbiProfileService>(); // .Services.AddTransient<IResourceOwnerPasswordValidator, OmbiOwnerPasswordValidator>()
// .AddTransient<IProfileService, OmbiProfileService>();
services.Configure<IdentityOptions>(options => services.Configure<IdentityOptions>(options =>
{ {
@ -151,10 +149,9 @@ namespace Ombi
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User); services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User);
//services.Configure<TokenAuthenticationOptions>(Configuration.GetSection("TokenAuthentication"));
services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings")); services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
services.Configure<UserSettings>(Configuration.GetSection("UserSettings")); services.Configure<UserSettings>(Configuration.GetSection("UserSettings"));
services.Configure<TokenAuthentication>(Configuration.GetSection("TokenAuthentication"));
services.Configure<LandingPageBackground>(Configuration.GetSection("LandingPageBackground")); services.Configure<LandingPageBackground>(Configuration.GetSection("LandingPageBackground"));
services.AddHangfire(x => services.AddHangfire(x =>
@ -179,8 +176,8 @@ namespace Ombi
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IMemoryCache cache) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IMemoryCache cache)
{ {
var options = (IOptions<UserSettings>) app.ApplicationServices.GetService( var tokenOptions = (IOptions<TokenAuthentication>)app.ApplicationServices.GetService(
typeof(IOptions<UserSettings>)); typeof(IOptions<TokenAuthentication>));
var ctx = (IOmbiContext)app.ApplicationServices.GetService(typeof(IOmbiContext)); var ctx = (IOmbiContext)app.ApplicationServices.GetService(typeof(IOmbiContext));
@ -190,26 +187,54 @@ namespace Ombi
Console.WriteLine($"Using Url {url.Value}:{port.Value} for Identity Server"); Console.WriteLine($"Using Url {url.Value}:{port.Value} for Identity Server");
app.UseIdentity(); app.UseIdentity();
app.UseIdentityServer();
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
#if !DEBUG #if !DEBUG
Authority = $"{url.Value}:{port.Value}", var audience = $"{url.Value}:{port.Value}";
#else #else
Authority = $"http://localhost:52038/",
var audience = $"http://localhost:52038/";
#endif #endif
ApiName = "api",
ApiSecret = "secret",
EnableCaching = true, var tokenValidationParameters = new TokenValidationParameters
CacheDuration = TimeSpan.FromMinutes(10), // that's the default {
RequireHttpsMetadata = options.Value.UseHttps, // FOR DEV set to false
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.Value.SecretKey)),
RequireExpirationTime = true,
ValidateLifetime = true,
ValidAudience = "Ombi",
ValidIssuer = "Ombi",
ClockSkew = TimeSpan.Zero
};
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
Audience = "Ombi",
AutomaticAuthenticate = true, AutomaticAuthenticate = true,
AutomaticChallenge = true, TokenValidationParameters = tokenValidationParameters
}); });
// app.UseIdentityServer();
// app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
// {
//#if !DEBUG
// Authority = $"{url.Value}:{port.Value}",
//#else
// Authority = $"http://localhost:52038/",
//#endif
// ApiName = "api",
// ApiSecret = "secret",
// EnableCaching = true,
// CacheDuration = TimeSpan.FromMinutes(10), // that's the default
// RequireHttpsMetadata = options.Value.UseHttps, // FOR DEV set to false
// AutomaticAuthenticate = true,
// AutomaticChallenge = true,
// });
loggerFactory.AddSerilog(); loggerFactory.AddSerilog();
if (env.IsDevelopment()) if (env.IsDevelopment())

View file

@ -16,11 +16,7 @@
"UseHttps": false "UseHttps": false
}, },
"TokenAuthentication": { "TokenAuthentication": {
"SecretKey": "secretkey_secretkey123!", "SecretKey": "secretkey_secretkey123!"
"Issuer": "OmbiIssuer",
"Audience": "OmbiAudience",
"TokenPath": "/api/v1/token/",
"CookieName": "access_token"
}, },
"LandingPageBackground": { "LandingPageBackground": {
"Movies": [ "Movies": [