@ -2,6 +2,7 @@
using System.Collections.Generic ;
using System.Collections.Generic ;
using System.IdentityModel.Tokens.Jwt ;
using System.IdentityModel.Tokens.Jwt ;
using System.Linq ;
using System.Linq ;
using System.Net.Http ;
using System.Security.Claims ;
using System.Security.Claims ;
using System.Text ;
using System.Text ;
using System.Threading.Tasks ;
using System.Threading.Tasks ;
@ -9,6 +10,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc ;
using Microsoft.AspNetCore.Mvc ;
using Microsoft.Extensions.Options ;
using Microsoft.Extensions.Options ;
using Microsoft.IdentityModel.Tokens ;
using Microsoft.IdentityModel.Tokens ;
using Ombi.Api ;
using Ombi.Core.Authentication ;
using Ombi.Core.Authentication ;
using Ombi.Helpers ;
using Ombi.Helpers ;
using Ombi.Models ;
using Ombi.Models ;
@ -23,18 +25,21 @@ namespace Ombi.Controllers
[Produces("application/json")]
[Produces("application/json")]
public class TokenController
public class TokenController
{
{
public TokenController ( OmbiUserManager um , IOptions < TokenAuthentication > ta , IAuditRepository audit , ITokenRepository token )
public TokenController ( OmbiUserManager um , IOptions < TokenAuthentication > ta , IAuditRepository audit , ITokenRepository token ,
IPlexOAuthManager oAuthManager )
{
{
_userManager = um ;
_userManager = um ;
_tokenAuthenticationOptions = ta . Value ;
_tokenAuthenticationOptions = ta . Value ;
_audit = audit ;
_audit = audit ;
_token = token ;
_token = token ;
_plexOAuthManager = oAuthManager ;
}
}
private readonly TokenAuthentication _tokenAuthenticationOptions ;
private readonly TokenAuthentication _tokenAuthenticationOptions ;
private readonly IAuditRepository _audit ;
private readonly IAuditRepository _audit ;
private readonly ITokenRepository _token ;
private readonly ITokenRepository _token ;
private readonly OmbiUserManager _userManager ;
private readonly OmbiUserManager _userManager ;
private readonly IPlexOAuthManager _plexOAuthManager ;
/// <summary>
/// <summary>
/// Gets the token.
/// Gets the token.
@ -43,6 +48,8 @@ namespace Ombi.Controllers
/// <returns></returns>
/// <returns></returns>
[HttpPost]
[HttpPost]
public async Task < IActionResult > GetToken ( [ FromBody ] UserAuthModel model )
public async Task < IActionResult > GetToken ( [ FromBody ] UserAuthModel model )
{
if ( ! model . UsePlexOAuth )
{
{
await _audit . Record ( AuditType . None , AuditArea . Authentication ,
await _audit . Record ( AuditType . None , AuditArea . Authentication ,
$"UserName {model.Username} attempting to authenticate" ) ;
$"UserName {model.Username} attempting to authenticate" ) ;
@ -62,8 +69,36 @@ namespace Ombi.Controllers
user . EmailLogin = true ;
user . EmailLogin = true ;
}
}
// Verify Password
// Verify Password
if ( await _userManager . CheckPasswordAsync ( user , model . Password ) )
if ( await _userManager . CheckPasswordAsync ( user , model . Password ) )
{
return await CreateToken ( model . RememberMe , user ) ;
}
}
else
{
// Plex OAuth
// Redirect them to Plex
// We need a PIN first
var pin = await _plexOAuthManager . RequestPin ( ) ;
//https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd
var url = await _plexOAuthManager . GetOAuthUrl ( pin . id , pin . code ) ;
if ( url = = null )
{
return new JsonResult ( new
{
error = "Application URL has not been set"
} ) ;
}
return new JsonResult ( new { url = url . ToString ( ) } ) ;
}
return new UnauthorizedResult ( ) ;
}
private async Task < IActionResult > CreateToken ( bool rememberMe , OmbiUser user )
{
{
var roles = await _userManager . GetRolesAsync ( user ) ;
var roles = await _userManager . GetRolesAsync ( user ) ;
@ -90,12 +125,12 @@ namespace Ombi.Controllers
var token = new JwtSecurityToken (
var token = new JwtSecurityToken (
claims : claims ,
claims : claims ,
expires : model . R ememberMe ? DateTime . UtcNow . AddDays ( 7 ) : DateTime . UtcNow . AddHours ( 5 ) ,
expires : r ememberMe ? DateTime . UtcNow . AddDays ( 7 ) : DateTime . UtcNow . AddHours ( 5 ) ,
signingCredentials : creds ,
signingCredentials : creds ,
audience : "Ombi" , issuer : "Ombi"
audience : "Ombi" , issuer : "Ombi"
) ;
) ;
var accessToken = new JwtSecurityTokenHandler ( ) . WriteToken ( token ) ;
var accessToken = new JwtSecurityTokenHandler ( ) . WriteToken ( token ) ;
if ( model . R ememberMe)
if ( r ememberMe)
{
{
// Save the token so we can refresh it later
// Save the token so we can refresh it later
//await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
//await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
@ -108,8 +143,30 @@ namespace Ombi.Controllers
} ) ;
} ) ;
}
}
[HttpGet("{pinId:int}")]
public async Task < IActionResult > OAuth ( int pinId )
{
var accessToken = await _plexOAuthManager . GetAccessTokenFromPin ( pinId ) ;
// Let's look for the users account
var account = await _plexOAuthManager . GetAccount ( accessToken ) ;
// Get the ombi user
var user = await _userManager . FindByNameAsync ( account . user . username ) ;
if ( user = = null )
{
// Could this be an email login?
user = await _userManager . FindByEmailAsync ( account . user . email ) ;
if ( user = = null )
{
return new UnauthorizedResult ( ) ;
return new UnauthorizedResult ( ) ;
}
}
}
return await CreateToken ( true , user ) ;
}
/// <summary>
/// <summary>
/// Refreshes the token.
/// Refreshes the token.