Skip to content
This repository has been archived by the owner on Oct 19, 2022. It is now read-only.

Commit

Permalink
Final cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
nbarbettini committed Jul 22, 2017
1 parent 840489c commit 2f9105c
Show file tree
Hide file tree
Showing 23 changed files with 112 additions and 359 deletions.
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ See the Compatibility Matrix on the [Stormpath-Okta Customer FAQ](https://stormp

No breaking changes from RC5.

Some internal cleanup:

* Removed the `StormpathTokenExchanger` and `SocialExecutor` classes (unused)
* Added an `aud` check to the local token verifier

## Version 4.0.0-RC5

* The `/oauth/token` route will now return `400 Bad Request` if the username or password fields are missing. This shouldn't be a breaking change compared to the previous Stormpath functionality, but earlier versions of the migration code failed with a less-helpful error message here.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
namespace Stormpath.Owin.Abstractions.Configuration
using System.Collections.Generic;
using System.Linq;

namespace Stormpath.Owin.Abstractions.Configuration
{
public sealed class OktaEnvironmentConfiguration
{
public OktaEnvironmentConfiguration(
string authorizationServerId,
IEnumerable<string> validAudiences,
string clientId,
string clientSecret)
{
AuthorizationServerId = authorizationServerId;
ValidAudiences = validAudiences.ToArray();
ClientId = clientId;
ClientSecret = clientSecret;
}

public string AuthorizationServerId { get; }

public string[] ValidAudiences { get; }

public string ClientId { get; }

public string ClientSecret { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static string CreateUriFromTemplate(
.Replace("{state}", state)
.Replace("{nonce}", nonce);

return $"{templated}"; //&prompt=login (TODO)
return $"{templated}";
}
}
}
1 change: 1 addition & 0 deletions src/Stormpath.Owin.Middleware/AccessTokenValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public Task<TokenIntrospectionResult> ValidateAsync(string token, CancellationTo
_keyProvider,
_configuration.Org,
_configuration.OktaEnvironment.AuthorizationServerId,
_configuration.OktaEnvironment.ValidAudiences,
_configuration.OktaEnvironment.ClientId,
_configuration.OktaEnvironment.ClientSecret);

Expand Down
49 changes: 49 additions & 0 deletions src/Stormpath.Owin.Middleware/Internal/OrphanAccessTokenBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Stormpath.Owin.Abstractions.Configuration;

namespace Stormpath.Owin.Middleware.Internal
{
internal sealed class OrphanAccessTokenBuilder
{
private readonly IntegrationConfiguration _configuration;

public OrphanAccessTokenBuilder(IntegrationConfiguration configuration)
{
_configuration = configuration;
}

public string Build(string id, string userId, int timeToLive)
{
var signingKey = _configuration.OktaEnvironment.ClientSecret;

var signingCredentials = new SigningCredentials(
new SymmetricSecurityKey(Encoding.ASCII.GetBytes(signingKey)),
SecurityAlgorithms.HmacSha256);

var now = DateTime.UtcNow;

var claims = new[]
{
new Claim("sub", id),
new Claim("jti", Guid.NewGuid().ToString()),
new Claim("iat", ((long)((now - Cookies.Epoch).TotalSeconds)).ToString(), ClaimValueTypes.Integer64),
new Claim("cid", _configuration.OktaEnvironment.ClientId),
new Claim("uid", userId)
};

var jwt = new JwtSecurityToken(
claims: claims,
issuer: _configuration.Application.Id,
expires: now + TimeSpan.FromSeconds(timeToLive),
notBefore: DateTime.UtcNow,
signingCredentials: signingCredentials,
audience: _configuration.OktaEnvironment.ClientId);

return new JwtSecurityTokenHandler().WriteToken(jwt);
}
}
}
70 changes: 0 additions & 70 deletions src/Stormpath.Owin.Middleware/Internal/StormpathTokenExchanger.cs

This file was deleted.

10 changes: 5 additions & 5 deletions src/Stormpath.Owin.Middleware/LocalAccessTokenValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public sealed class LocalAccessTokenValidator
private readonly IKeyProvider _keyProvider;
private readonly string _orgHref;
private readonly string _authorizationServerId;
private readonly string[] _validAudiences;
private readonly string _clientId;
private readonly string _clientSecret;

Expand All @@ -23,6 +24,7 @@ public LocalAccessTokenValidator(
IKeyProvider keyProvider,
string orgHref,
string authorizationServerId,
IEnumerable<string> validAudiences,
string clientId,
string clientSecret)
{
Expand All @@ -31,14 +33,13 @@ public LocalAccessTokenValidator(

_orgHref = orgHref;
_authorizationServerId = authorizationServerId;
_validAudiences = validAudiences.ToArray();
_clientId = clientId;
_clientSecret = clientSecret;
}

public async Task<JwtSecurityToken> ValidateSecurityTokenAsync(string token, CancellationToken cancellationToken)
{
// TODO need ITs for this

var param = new TokenValidationParameters()
{
ValidateIssuer = true,
Expand All @@ -48,9 +49,8 @@ public async Task<JwtSecurityToken> ValidateSecurityTokenAsync(string token, Can
RequireSignedTokens = true,
ValidateIssuerSigningKey = true,
IssuerSigningKeyResolver = await _keyProvider.GetSigningKeyResolver(cancellationToken),

// TODO what will the standard audience be?
ValidateAudience = false
ValidateAudience = true,
ValidAudiences = _validAudiences,
};

try
Expand Down
54 changes: 4 additions & 50 deletions src/Stormpath.Owin.Middleware/LoginExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,15 @@
// limitations under the License.
// </copyright>

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Stormpath.Owin.Abstractions;
using Stormpath.Owin.Abstractions.Configuration;
using Stormpath.Owin.Middleware.Internal;
using Stormpath.Owin.Middleware.Model.Error;
using Stormpath.Owin.Middleware.Okta;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Stormpath.Owin.Middleware
{
Expand Down Expand Up @@ -85,7 +81,6 @@ public LoginExecutor(
password,
cancellationToken);

// todo move this into a new class TokenValidator
var remoteValidator = new RemoteTokenValidator(
_oktaClient,
_configuration.OktaEnvironment.AuthorizationServerId,
Expand Down Expand Up @@ -134,53 +129,12 @@ public async Task<GrantResult> ClientCredentialsGrantAsync(

return new GrantResult
{
AccessToken = BuildClientCredentialsAccessToken(id, userId, ttl),
AccessToken = new OrphanAccessTokenBuilder(_configuration).Build(id, userId, ttl),
TokenType = "Bearer",
ExpiresIn = ttl,
// Scope = TODO
};
}

private string BuildClientCredentialsAccessToken(string id, string userId, int timeToLive)
{
var signingKey = _configuration.OktaEnvironment.ClientSecret;

var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(
new SymmetricSecurityKey(Encoding.ASCII.GetBytes(signingKey)), SecurityAlgorithms.HmacSha256);

var now = DateTime.UtcNow;

var claims = new[]
{
new Claim("sub", id),
new Claim("jti", Guid.NewGuid().ToString()),
new Claim("iat", ((long)((now - Cookies.Epoch).TotalSeconds)).ToString(), ClaimValueTypes.Integer64),
new Claim("cid", _configuration.OktaEnvironment.ClientId),
new Claim("uid", userId)
};

var jwt = new JwtSecurityToken(
claims: claims,
issuer: _configuration.Application.Id,
expires: now + TimeSpan.FromSeconds(timeToLive),
notBefore: DateTime.UtcNow,
signingCredentials: signingCredentials);
// TODO audience
// TODO scope

return new JwtSecurityTokenHandler().WriteToken(jwt);
}

// TODO restore
//public async Task<LoginResult> TokenExchangeGrantAsync(
// IOwinEnvironment environment,
// ICompatibleOktaAccount account,
// CancellationToken cancellationToken)
//{
// var tokenExchanger = new StormpathTokenExchanger(_client, application, _configuration, _logger);
// return await tokenExchanger.ExchangeAsync(account, cancellationToken);
//}

public async Task<ICompatibleOktaAccount> HandlePostLoginAsync(
IOwinEnvironment context,
GrantResult grantResult,
Expand Down
1 change: 0 additions & 1 deletion src/Stormpath.Owin.Middleware/LogoutExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public async Task HandleLogoutAsync(IOwinEnvironment context, CancellationToken
var preLogoutContext = new PreLogoutContext(context, account);
await _handlers.PreLogoutHandler(preLogoutContext, cancellationToken);

// TODO delete tokens for other types of auth too
await RevokeCookieTokens(cookieParser, cancellationToken);
await RevokeHeaderToken(context, cancellationToken);

Expand Down
17 changes: 17 additions & 0 deletions src/Stormpath.Owin.Middleware/Okta/AuthorizationServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Generic;

namespace Stormpath.Owin.Middleware.Okta
{
public sealed class AuthorizationServer
{
public string Id { get; set; }

public string Name { get; set; }

public string Description { get; set; }

public List<string> Audiences { get; set; }

public string Issuer { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/Stormpath.Owin.Middleware/Okta/IOktaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,7 @@ Task SendPasswordResetEmailAsync(
Task<Group[]> GetGroupsForUserIdAsync(string userId, CancellationToken cancellationToken);

Task<ShimApiKey> GetApiKeyAsync(string apiKeyId, CancellationToken cancellationToken);

Task<AuthorizationServer> GetAuthorizationServerAsync(string authorizationServerId, CancellationToken cancellationToken);
}
}
4 changes: 3 additions & 1 deletion src/Stormpath.Owin.Middleware/Okta/OktaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,6 @@ public Task<TokenIntrospectionResult> IntrospectTokenAsync(
};
request.Content = new FormUrlEncodedContent(parameters);

// todo why can't I remove this await?
return SendAsync<TokenIntrospectionResult>(request, cancellationToken);
}

Expand Down Expand Up @@ -530,5 +529,8 @@ public async Task<ShimApiKey> GetApiKeyAsync(string apiKeyId, CancellationToken

return null;
}

public Task<AuthorizationServer> GetAuthorizationServerAsync(string authorizationServerId, CancellationToken cancellationToken)
=> GetResource<AuthorizationServer>($"{ApiPrefix}/authorizationServers/{authorizationServerId}", cancellationToken);
}
}
7 changes: 2 additions & 5 deletions src/Stormpath.Owin.Middleware/OrphanAccessTokenValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ public OrphanAccessTokenValidator(

public JwtSecurityToken ValidateSecurityToken(string token)
{
// TODO need ITs for this

var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_clientSecret));

var param = new TokenValidationParameters()
Expand All @@ -42,9 +40,8 @@ public JwtSecurityToken ValidateSecurityToken(string token)
RequireSignedTokens = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,

// TODO what will the standard audience be?
ValidateAudience = false
ValidateAudience = true,
ValidAudience = _clientId,
};

try
Expand Down
8 changes: 4 additions & 4 deletions src/Stormpath.Owin.Middleware/Route/AbstractRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ public async Task<bool> InvokeAsync(IOwinEnvironment owinContext)
if (contentNegotiationResult.ContentType == ContentType.Json)
{
// Sanitize framework-level errors
await Error.Create(owinContext, 400, ex.Message, owinContext.CancellationToken);
await Error.Create(owinContext, 500, ex.Message, owinContext.CancellationToken);
return true;
}
else
{
// todo handle framework errors
_logger.LogError(1007, ex, nameof(InvokeAsync));
throw;
// TODO return HTML?
await Error.Create(owinContext, 500, ex.Message, owinContext.CancellationToken);
return true;
}
}
}
Expand Down
Loading

0 comments on commit 2f9105c

Please sign in to comment.