@ -2,6 +2,7 @@
using System.Collections.Generic ;
using System.IdentityModel.Tokens.Jwt ;
using System.Linq ;
using System.Net.Http ;
using System.Security.Claims ;
using System.Text ;
using System.Threading.Tasks ;
@ -9,6 +10,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc ;
using Microsoft.Extensions.Options ;
using Microsoft.IdentityModel.Tokens ;
using Ombi.Api ;
using Ombi.Core.Authentication ;
using Ombi.Helpers ;
using Ombi.Models ;
@ -23,18 +25,21 @@ namespace Ombi.Controllers
[Produces("application/json")]
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 ;
_tokenAuthenticationOptions = ta . Value ;
_audit = audit ;
_token = token ;
_plexOAuthManager = oAuthManager ;
}
private readonly TokenAuthentication _tokenAuthenticationOptions ;
private readonly IAuditRepository _audit ;
private readonly ITokenRepository _token ;
private readonly OmbiUserManager _userManager ;
private readonly IPlexOAuthManager _plexOAuthManager ;
/// <summary>
/// Gets the token.
@ -44,71 +49,123 @@ namespace Ombi.Controllers
[HttpPost]
public async Task < IActionResult > GetToken ( [ FromBody ] UserAuthModel model )
{
await _audit . Record ( AuditType . None , AuditArea . Authentication ,
if ( ! model . UsePlexOAuth )
{
await _audit . Record ( AuditType . None , AuditArea . Authentication ,
$"UserName {model.Username} attempting to authenticate" ) ;
var user = await _userManager . FindByNameAsync ( model . Username ) ;
if ( user = = null )
{
// Could this be an email login?
user = await _userManager . FindByEmailAsync ( model . Username ) ;
var user = await _userManager . FindByNameAsync ( model . Username ) ;
if ( user = = null )
{
return new UnauthorizedResult ( ) ;
}
// Could this be an email login?
user = await _userManager . FindByEmailAsync ( model . Username ) ;
user . EmailLogin = true ;
}
if ( user = = null )
{
return new UnauthorizedResult ( ) ;
}
// Verify Password
if ( await _userManager . CheckPasswordAsync ( user , model . Password ) )
{
var roles = await _userManager . GetRolesAsync ( user ) ;
user . EmailLogin = true ;
}
if ( roles . Contains ( OmbiRoles . Disabled ) )
// Verify Password
if ( await _userManager . CheckPasswordAsync ( user , model . Password ) )
{
return new UnauthorizedResult ( ) ;
return await CreateToken ( model . RememberMe , user ) ;
}
user . LastLoggedIn = DateTime . UtcNow ;
await _userManager . UpdateAsync ( user ) ;
var claims = new List < Claim >
{
new Claim ( JwtRegisteredClaimNames . Sub , user . UserName ) ,
new Claim ( ClaimTypes . NameIdentifier , user . Id ) ,
new Claim ( ClaimTypes . 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 : model . RememberMe ? DateTime . UtcNow . AddDays ( 7 ) : DateTime . UtcNow . AddHours ( 5 ) ,
signingCredentials : creds ,
audience : "Ombi" , issuer : "Ombi"
) ;
var accessToken = new JwtSecurityTokenHandler ( ) . WriteToken ( token ) ;
if ( model . RememberMe )
}
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 )
{
// Save the token so we can refresh it later
//await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
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 ) ;
if ( roles . Contains ( OmbiRoles . Disabled ) )
{
return new UnauthorizedResult ( ) ;
}
user . LastLoggedIn = DateTime . UtcNow ;
await _userManager . UpdateAsync ( user ) ;
var claims = new List < Claim >
{
new Claim ( JwtRegisteredClaimNames . Sub , user . UserName ) ,
new Claim ( ClaimTypes . NameIdentifier , user . Id ) ,
new Claim ( ClaimTypes . 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 : rememberMe ? DateTime . UtcNow . AddDays ( 7 ) : DateTime . UtcNow . AddHours ( 5 ) ,
signingCredentials : creds ,
audience : "Ombi" , issuer : "Ombi"
) ;
var accessToken = new JwtSecurityTokenHandler ( ) . WriteToken ( token ) ;
if ( rememberMe )
{
// Save the token so we can refresh it later
//await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
}
return new JsonResult ( new
{
access_token = accessToken ,
expiration = token . ValidTo
} ) ;
}
[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 ) ;
return new JsonResult ( new
if ( user = = null )
{
access_token = accessToken ,
expiration = token . ValidTo
} ) ;
return new UnauthorizedResult ( ) ;
}
}
return new UnauthorizedResult ( ) ;
return await CreateToken ( true , user ) ;
}
/// <summary>
@ -127,7 +184,7 @@ namespace Ombi.Controllers
{
return new UnauthorizedResult ( ) ;
}
throw new NotImplementedException ( ) ;
}