Difference between Token Interceptor and Token Session Interceptor? - struts2

I Know that both the interceptors are used to prevent duplicate form submissions? But What really are the difference between both of them?
Which one has extra edge over other?

The tokenSession extends token interceptor, they are both used to ensure that only one request per token is processed. The difference is in the handling of the invalid tokens.
When invalid token is found the token interceptor just returns invalid.token result. The tokenSession interceptor on invalid token will try to display the same response that would have been displayed in case of valid token.
Some pseudo code for illustrating workflow of the tokenSession interceptor:
intercept() {
if(validToken){
storeInvocation();
return invocation.invoke();
}else {
ActionInvocation storedInvocation = loadStoredInvocation();
// ...
return storedInvocation.getResultCode();
}
}

Related

Adding a Policy-based Authorization skips JWT bearer token authentication check?

I have a REST API service that implements JWT bearer token based authentication obtained from Azure AD.
// add support for custom Authorization policies
services
.AddAuthorization(authoptions =>
{
authoptions.AddPolicy("MemberOfUsersADGroup", policy =>
policy.Requirements.Add(new IsMemberOfUsersADGroup())
);
})
.AddSingleton<IAuthorizationHandler, IsMemberOfUsersADGroupAuthHandler>();
// add support for this service to recieve OAUTH2 JWT bearer tokens
services
.AddAuthentication(authOptions =>
{
authOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// token validation (REQUIRED)
options.Audience = "AUDIENCE GUID";
options.Authority = String.Format("https://login.microsoftonline.com/[TENANTGUID]/");
});
And here's how the policy authorizaton handler is implemented. IT returns success unconditionally.
public class IsMemberOfSenseiUsersADGroup : IAuthorizationRequirement
{
}
public class IsMemberOfUsersADGroupAuthHandler : AuthorizationHandler<IsMemberOfUsersADGroup>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsMemberOfUsersADGroup requirement)
{
// unconditional success for now
context.Succeed(requirement);
return Task.CompletedTask;
}
}
CASE 1
If I decorate my controller like this, and call without a bearer token, then I get a 401 as expected.
[Authorize]
[Route("api/dostuff")]
public class DoStuffController : Controller
{
CASE 2
HOWEVER, if I decorate my controller with the Policy, and call without a bearer token, then the REST API call passes fine and doesnt require a bearer token at all!!! I see the call enter into the AuthHandler HandleRequirementAsync() and then it succeeds, even tho bearer tokens were not passed in.
[Authorize(Policy = "MemberOfUsersADGroup")]
[Route("api/dostuff")]
public class DoStuffController : Controller
{
I am unable to explain this behavior at all. I am glad I caught this in my testing because I assumed the policy check is additive (as indicated by "AddPolicy" call), but it seems to replace the entire validation chain incl. the one done by JWT bearer middleware in CASE 1.
Am I doing something wrong? Is it related to the ordering of the Add*** calls made in ConfigureServices() How do I make sure the JWT bearer token validation occurs no matter if the policy authhandler checks pass or not?
That's the expected behavior.
If you want your authorization policy to reject unauthenticated requests, simply call builder.RequireAuthenticatedUser().
I've had a same problem. My workaround was that I put controller under default [Authorize] attribute and then every action has it's own policy [Authorize(Policy = "MemberOfUsersADGroup")]. To me it wasn't such a big deal because I had only one controller which action's was under the same policy. RequireAuthenticatedUser and similar wasn't necessary.

How do I set up an OAuth2RestTemplate with client credentials and automatic token refresh in spring-security-oauth 2.2.1.RELEASE

I am implementing a client that authenticates with OAuth2 against WSO2 and I have serious trouble refreshing the access token, getting 401 UNAUTHORIZED. While I have already found out, what the Spring OAuth2 code does, I do not know why its behavior was changed in 2.2.1.RELEASE and to me it seems plain wrong. Actually using 2.0.14.RELEASE works.
Before I am going to show to you, what I have done and what I have already found out, let me formulate my question:
How am I supposed to realize an OAuth2 client with automatic token refresh with client credentials instead of user credentials?
So here is, what I have implemented so far. The client configures an OAuth2RestTemplate with ResourceOwnerPasswordResourceDetails with isClientOnly flag true, as there are no user sessions. The client session can successfully be established and an access token and a refresh token are set.
#Bean
protected OAuth2ProtectedResourceDetails resource() {
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails() {
#Override
public boolean isClientOnly() {
return true;
}
};
List<String> scopes = new ArrayList<>(2);
scopes.add("write");
scopes.add("read");
resource.setScope(scopes);
resource.setGrantType("password");
resource.setAccessTokenUri(TOKEN_URL);
resource.setClientId(MY_CLIENT_ID);
resource.setClientSecret(MY_CLIENT_SECRET);
resource.setUsername(MY_SERVICE_USER);
resource.setPassword(MY_SERVICE_USER_PW);
return resource;
}
#Bean
public OAuth2RestOperations restTemplate() {
AccessTokenRequest atr = new DefaultAccessTokenRequest();
OAuth2RestTemplate template = new OAuth2RestTemplateWithBasicAuth(resource(), new DefaultOAuth2ClientContext(atr));
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
interceptors.add(new LoggingRequestInterceptor());
template.setInterceptors(interceptors);
template.setRetryBadAccessTokens(true);
return template;
}
So far so good. I have verified that this basically works.
But as soon as the access token expires I frequently run into 401 errors, because the token refresh is not executed. Instead, an ordinary authentication request is carried out, but using the client key and secret instead of user/password. To cut a long story short, I have debugged my way through spring-security-oauth2 into AccessTokenProviderChain#obtainAccessToken and found out, that whether a token refresh request is executed is decided upon in the following bit of code. See on Github
if (resource.isClientOnly() || (auth != null && auth.isAuthenticated())) { // P1
existingToken = request.getExistingToken();
if (existingToken == null && clientTokenServices != null) {
existingToken = clientTokenServices.getAccessToken(resource, auth);
}
if (existingToken != null) {
if (existingToken.isExpired()) {
if (clientTokenServices != null) {
clientTokenServices.removeAccessToken(resource, auth);
}
OAuth2RefreshToken refreshToken = existingToken.getRefreshToken();
if (refreshToken != null && !resource.isClientOnly()) { // P2
accessToken = refreshAccessToken(resource, refreshToken, request);
}
}
else {
accessToken = existingToken;
}
}
}
As you can see at P1, the block is entered if either an authorized user session exists (auth) or the resource is configured as clientOnly. As I do not have users but I am in a linked service scenario, I have isClientOnly() == true && auth == null. But at P2 the final decision upon actually doing the refresh is contraticted by requiring !isClientOnly(). So this effectively bans refresh requests in client only scenarios.
This was the way to go in versions before 2.2.1 and I have found out, that this seems to be a fix to the following Issue. To me this seems plain wrong.
Furthermore, to me the patch appears to break client functionality to fix an actual server misbehavior. As you can see in the issue discussion, I have already commented the there. But as that issue is closed and the spring-security-oauth2 forum states that discussions should be held here on StackOverflow, I am asking for help here.
Again the question: How should a client application be configured to consume OAuth2 secured services via OAuth2RestTemplate and an access token runtime of an hour and refresh token runtime of lets say two hours.

allow mvc5 c# webapi so that only my app can access it

I am making the api calls through the controller action method as below. The following is the working code of it.
But I want to secure the webapi so that only my application can access it. I have seen sources with login credentials
but in my case it is a public facing website with no login users.
Only the calls from my application should access it. Could anyone please suggest what can be done. or Is my current code with ValidateReferrer is suffice to handle?
[HttpGet]
[ValidateReferrer]
[ActionName("GetFind")]
[CacheOutput(ClientTimeSpan = 300, ServerTimeSpan = 300)]
public ApiQueryResponse GetFind(string query)
{
return _Worker.GetFind(query);
}
Validate Referrer in the controller has the following implementation:
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext == null)
{
throw new System.Web.HttpException("No Http context, request not allowed.");
}
else
{
if (filterContext.HttpContext.Request.UrlReferrer == null)
{
throw new System.Web.HttpException("Referrer information missing, request not allowed.");
}
else if (filterContext.HttpContext.Request.UrlReferrer.Host != filterContext.HttpContext.Request.Url.Host)
{
throw new System.Web.HttpException(string.Format("Possible cross site request forgery attack, request sent from another site: {0}", filterContext.HttpContext.Request.UrlReferrer.Host));
}
}
}
In the worker class,
public ApiQueryResponse GetFind(string query)
{
var results = GetResults(Settings.ApiKey, SetFindParameters(query), Resource);
return results;
}
private ApiQueryResponse GetResults(string apiKey, string parameterQuery, string Resource)
{
var results = new ApiQueryResponse();
if (apiKey != null && !String.IsNullOrWhiteSpace(apiKey))
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync(string.Format("{0}/{1}?{2}&key={3}", WebApiUrl, Resource, parameterQuery, apiKey)).Result;
if (response.IsSuccessStatusCode)
{
var responseBodyAsText = response.Content.ReadAsStringAsync().Result;
results = JsonConvert.DeserializeObject<ApiQueryResponse>(responseBodyAsText);
}
}
}
return results;
}
Again this is the case where you have to authenticate your "application" but not users. If you check facebook/twitter/gmail api's, they have a client secret and client id to authenticate the application. But still there will be an "Authorize" call made with this id and secret for which the api returns a token and this token is used henceforth to authorize the other requests. This token will also have an expiry and there are methods to get refresh tokens.
Thus said, you have to take a call on how much security you have to implement for your api's. You could have a similar approach where your client first asks for a security token by providing the client id and secret (which should really be a secret). You can check this id and secret against your store (may be database) and if that passes the validation, you can send back a token which you could authroize using [Authroize] attribute or by custom validation.
How to create tokens should be another discussion IMO. Simple approach is mentioned here for eg- how to generate a unique token which expires after 24 hours?. There are other standard ways of generating tokens JWT/OAuth tokens.
EDIT
As a simple approach (not taking much security aspects into consideration) would be:
Create an app secret (may be a Guid value)
While sending request, take current timestamp and encrypt (have your
own encrypt and decrypt logic) the timestamp with the app secret. Lets call that encrypted value as 'token'
Pass the token in your request header (may be a custom header,say,
x-my-auth)
In the api, have a custom authorize filter
In the custom filter, overridden OnAuthroizeCore method, get the
token from request header
Decrypt the token using the same app secret and you will get the
timestamp sent from the client
If decryption is fine, then we are through the first step/ or the
token passed the first step
Additionaly, check whether the difference between the current time
and the time decrypted from token is more than 5(*you can have your
own expiry value)
If the difference is more than your expiry limit, return false which
would throw unauthorized exception back to the client (do the same if the token fails to decrypt)
The expiry check is to handle the scenario where someone hacking your
token from the request and then using it afterwards. In case if he
uses the token after your expiry, this would throw unauthorized
Consider the above logic and entire description just as a "food for thought" and DO NOT use it without proper research and understanding. My idea was to give some basic idea about the application authentication until someone really good at this writes up a really nice article in this post

Override error code on AuthorizationCodeProvider.Create

This question is about the implementation of the Authorization Code flow using Owin in Asp.net Wep Api.
I was trying to handle some error that might happen on my AuthorizationCode code creation. Apparently I can't redirect my self to the Client Redirect URI with he correct error code which is "server_error"
The following is my code :
private static void CreateAuthorizationCode(AuthenticationTokenCreateContext context)
{
try
{
//Some Code to create and save the AuthorizationCode that can throw an Exception
context.SetToken(code);
}
catch (Exception ex)
{
logger.Fatal(ex);
var redirectUri = GetRedirectUri();
var redirectLocation = string.Format("{0}?code={1}", redirectUri, "server_error");
context.Response.Redirect(redirectLocation);
}
}
But I get redirected by the framework to the redirect Uri with https://redirecturi?error=unsupported_response_type !
Is this a normal behavior ? Or maybe there is any other way to handle those kind of scenario and set by myself the error code !?
PS : I created an issue in Github about that : https://github.com/aspnet/Security/issues/375 no answer so far !
Thank you.
Is this a normal behavior ? Or maybe there is any other way to handle those kind of scenario that I'm missing?
Normal, I dunno. But expected, definitely: when using an IAuthenticationTokenProvider, you're not supposed to alter the HTTP response.
Why there is not way to set by myself the error using the AuthenticationTokenCreateContext object like context.SetError("my_error") ?
Unlike the ValidateAuthorizeRequest notification, it hasn't been designed to allow you to return an error.
Sadly, there's no way to return a server_error response from an IAuthenticationTokenProvider, since OAuthAuthorizationServerHandler will always use unsupported_response_type if you don't provide an authorization code: https://github.com/jchannon/katanaproject/blob/master/src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerHandler.cs#L204
FYI, this is something we fixed recently in AspNet.Security.OpenIdConnect.Server (a fork of the OAuth2 authorization server shipped with Katana 3): https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/issues/112#issuecomment-125040925. If your custom code returns a null authorization code, a server_error response will be automatically returned to the client application.

Cross platform authentication using ASP.NET Web API

How do I even begin coding authentication using ASP.NET Web API so it is cross-platform to support desktop, mobile and web? I'd read of some methods of doing RESTful authentication, such as using tokens in the header.
Are there any example projects out there that utilizes this method?
Questions:
If not how do I fix the [Authorize] attribute to read the token?
How do I generate this token? I dont think i can use formsauthentication because that uses cookies.
How do I handle the actual authorization, do the client send raw password and username then I generate the token or is there some other way?
How do I handle when my website is using it? I heard this is handled differently than when an app is using it, such as getting the domain and authorizing it.
I think tokens would be a solid way to go. Forms authentication is based on cookies for the web. Not the most idea situation for all non browser clients though.
What I'd suggest is creating a custom AuthorizationFilterAttribute and overriding the OnAuthorization method. In that method, you could check for the existence of a token that you've issued to the client after they've supplied valid credentials. You can use this attribute on any method or controller you want validated. Here's a sample you might reference
public class AuthorizeTokenAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext != null)
{
if (!AuthorizeRequest(actionContext.ControllerContext.Request))
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized) { RequestMessage = actionContext.ControllerContext.Request };
}
return;
}
}
private bool AuthorizeRequest(System.Net.Http.HttpRequestMessage request)
{
bool authorized = false;
if (request.Headers.Contains(Constants.TOKEN_HEADER))
{
var tokenValue = request.Headers.GetValues("TOKEN_HEADER");
if (tokenValue.Count() == 1) {
var value = tokenValue.FirstOrDefault();
//Token validation logic here
//set authorized variable accordingly
}
}
return authorized;
} }
TOKEN_HEADER is just a string representing an HTTP header that the client should pass back for authenticated requests.
So let's walk through it
Client requests secure data
Client is not authorized, return a response with an Unauthorized status code
Client sends credentials to authenticate, which should be secured via HTTPS
Once validated, client receives a token via an HTTP header, or whatever works for you
Client tries requesting secure data again, this time attached the token to the request
The AuthorizeTokenAttribute will validate the token and allow the action to execute.
Also, check this post by John Petersen. Making your ASP.NET Web API’s secure
There are lots of ways to authenticate users for a REST service. Using tokens is possible but just using Basic Authentication is even simpler and about as standard and cross platform as you can go.
Don't confuse authorization with authentication. The [Authorize] attribute is all about authorization but only after a user has been authenticated using some other mechanism. Authorization is completely useless without doing proper authentication first.
The best resource to check is Dominick Baier who is an expert on the subject.
I use a very simple approach:
define an access profile with its unique accessId and accessKey (e.g. MD5 hashed GUID value)
store such access profile in database
every request (GET/POST/etc.) must supply accessId, queryHash (MD5 hash value represents the query) and signature (MD5 hash value of queryHash + accessKey). Of course the client needs keep the accessKey in a secure place!!!
server gets the request will check the accessId and the signature using the same calculation algorithm to reject or grant the access (authenticate)
further authorization can be done on request type basis utilizing the access profile
the service with this approach using the new ASP.NET MVC web API can serve whatever type of client: browser/javascript and native(desktop or mobile) etc.
U can use ActionFilterAttribute and override the OnActionExecuting method.
Later on register this filter in global.cs to apply this filter for all the actions like this in Application Start method
var config = GlobalConfiguration.Configuration;
config.Filters.Add(new CustomAuthAttribute ());
{
namespace Customss
{
Public class CustomAuthAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
// To inforce HTTPS if desired , else comment out the code
if (!String.Equals(actionContext.Request.RequestUri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
{
Content = new StringContent("HTTPS Required")
};
return;
}
// get toekn from the header
var userToken = actionContext.Request.Headers.GetValues("UserToken");
// Customer Logic to check the validity of the token.
// U can have some DB logic to check , custom STS behind or some loca cache used to compare the values
}
}
}
}

Resources