Redirecting a signal returning an error to another signal - nsurlsession

So my use case is that I have an HTTP request (fired using -[NSURLSession rac_dataWithRequest:]) that can return a status code of 403.
When this happens I would like to catch that, and redirect to another SignalProducer that requests an authentication token. When that SignalProducer successfully completes, I would like to redirect back to the original rac_dataWithRequest.
How would I best do this? I'm using ReactiveCocoa 4.x and Swift 2.

do you need to hand the authentication token back to the original request before retrying? If yes, then this won't help you, sorry.
I assumed that you just need to fire the authentication request once and then retry the original request. E.g. your authentication request sets the HTTP Authorization header of your HTTP client so that the next request is automatically authorised...
This gist has the contents of a Playground that illustrates the solution. This gist is the result of me playing around to find a solution, requests are mocked, ...
Lets say you have a SignalProducer for your request:
let request = SignalProducer<Response, NSError> {
// Perform your request that needs authentication here
}
And another one for your authentication request:
let authorize = SignalProducer<Void, NSError> {
// Perform your request that needs authentication here
}
Now you can use flatMapErrors (formerly catch) and retry:
request.flatMapError { error -> SignalProducer<String, NSError> in
if(error.code == 403) {
return authorize.then(SignalProducer(error: error))
} else {
return SignalProducer(error: error)
}
}.retry(1)
So, we catch errors of the original request and, if the error code is 403, we perform the authorize request. Then, we still forward the catched error. Otherwise, we just forward the error.
Forwarding the error after the authorize request is important, otherwise, retry will not restart the original request.
The problem with this however is, that it will retry on every error, not just when the original request returns 403...

Related

Authorization for HttpEndpoints

"Elsa" Version="2.8.1"
"Elsa.Activities.Http" Version="2.8.1"
"Elsa.Server.Api" Version="2.8.1"
I am trying to enable HttpEndpoint authorization for workflows which are started by an HTTP call.
Even if I enable the Authorize setting in Security tab of the incoming HTTP request activity, that seems to have no impact as I can still start the workflow without a Bearer token when calling the endpoint.
Screenshot of HttpActivity.
If I create a sample controller in the same project and add an [Authorize] attribute to it, it works as expected (401 Error on invalid/missing token).
Sample controller:
[HttpGet("auth-test")]
[Authorize]
public async Task<IActionResult> TestAuth()
{
return Ok();
}
Authentication & authorization setup:
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration, "AzureAd");
<..>
builder.Services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.AddRequirements(new MyApiRequirement())
.Build();
});
I even tried specifying an non-existing policy name for the Policy input field, to check if that would fail some evaluations - no errors, accessible without any tokens.
Could someone please help identifying what am I missing?

How to declare spring security to return response code with custome login-form when login is redirected?

Whenever the application gets redirected to custom login form the response code is always 200. Is there any way to identify whether the current 200 status code is either from the URL requested from user OR the custom login URL redirected by spring security.
.and().formLogin()
.loginPage("/login").usernameParameter("userName").passwordParameter("password")
Reason for the ask- Because the response from actual user request never come back as failure, spring always just send 200 response with login form.
I have set the customized login form which gets displayed when user send a direct URL request which needs to be authorized and this works fine but here is the catch. so lets say, i requested a URL which needs authentication, and expect that api should returns 401, unauthorized. Obviously spring intercepts the request and it does not reach the backend controller but instead spring redirects to loginform with "200" success response code.
so i will not be able to check whether user has been intercepted and redirected to formlogin by checking the response code. Now why do i need it? because i am using angularJS in front end, so i have different angularJS controllers for all the pages. Now lets say i requested for profile page which needs authentication so i can not just return formlogin until i assign correct angularJS controller to the page. so i need to know when the user has been redirected to formlogin using response code returned.
Another reason is , i am using AgularJS interceptors to check response sucess and failures, so i expectc that once my API call gets rejected due to unauthorized access, i should go into "response rejected" interceptor block but see this comes to "response success" interceptor block as Spring has intercepted the request and change it to 200 success with login form page URL returned.
You can try:
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("userName")
.passwordParameter("password")
.successHandler(
( request, response, authentication ) -> {
response.setHeader( "Location", "Your angular url");
response.setHeader( "message", "authenticated" ); // <-custom http header as redirection does not allow content inside response body
response.setStatus( HttpServletResponse.SC_FOUND ); // <- redirection status
}
)
.failureHandler(
( request, response, authenticationException ) -> {
response.setHeader( "Location", "Your angular url");
response.setHeader( "message", "error" );
response.setStatus( HttpServletResponse.SC_FOUND );
}
);
There are endless options!! If i haven't understand your question let me know.
Cheers,

spring cloud gateway, avoid routing to a uri

I'm looking for a way to execute some filters and predicates on a request, and at the end simply return a response to the user, instead of routing it to a specific URI.
For example, a user is calling /auth/token and my gateway has a filter that generates a token and transforms the body of the response (using the ModifyResponseBodyGatewayFilterFactory).
When adding a filter that simply returns response.setCompleted(), the body returns empty and the status code is always 200.
return (exchange, chain) -> {
return modifyResponseBodyGatewayFilterFactory.apply(c -> c.setRewriteFunction(Object.class, String.class, SomeBody))
.filter(exchange, chain)
.then(exchange.getResponse().setComplete());
}
How can I return a specific body to the user, without routing to a URI?
Thanks in advance!
I couldn't find a solution, so instead, I've created a web flux controller for this specific request.
This is a good enough solution for me.

Laravel 5.5 Request is empty in Restful controller

I have such a route in my routes/web.php
Route::resource('/api/surveys', 'SurveyController');
As documentation says, it creates all needed routes for API. This is a function, that gets executed when I go for /api/surveys route:
public function index()
{
$request = request();
if(!$request->hasHeader('token')) {
return "No auth token found.";
}
$tokenCheck = $this->userService->isTokenValid($request->header('token'));
if($tokenCheck !== true) {
return $tokenCheck;
}
return $this->surveyService->all();
}
What it does, it checks if token header parameter is set, if not, it returns an error, if yes, it checks if token is valid and etc. if everything is OK, it should return surveys from database.
public function surveys() {
$request = \Request::create('/api/surveys', 'GET');
$request->headers->set('Accept', 'application/json');
$request->headers->set('token', \Cookie::get('token'));
$response = \Route::dispatch($request);
print_r('<pre>');
print_r($response);
print_r('</pre>');
}
I have a website, that should use that API I just created to get all survey records. I create a new request object, set header "token" with token I get from a cookie and then try to dispatch and get a response. But the problem is that everytime I get "No auth token found." error. That means $request->hasHeader('token') returns false, even tough I set it here in my request. If I print_r $request->all() in Restful controller, I get an empty array.
I tried Postman to access this API with token parameter, and it works fine in postman, but here, it seems that Request disappears while it travels to API controller.
What I did wrong here?
When you manually create a request and dispatch it, that works to get the routing to call the correct controller, however that does not affect the request that is bound in the container.
When your "fake" request is handled by the api controller, the request that it pulls out of the container is the original "real" request that was made by the user.
Instead of dispatching the route with your new request, you will need to app()->handle($request) the new request. This, however, will completely replace the original "real" request with your new "fake" request, so everything from the original request will be lost.
Having said all that, this method of consuming your own api is discouraged, even by Taylor. You can read his comment on this Github issue. So, consuming your own api like this may work, but you may also run into some other unforeseen issues.
The more appropriate solution would be to extract out the logic called by the api routes to another class, and then call that extracted logic from both your api routes and your web routes.

Returning HTTP 403 substatus from Asp.Net WebApi controller

I'd like to return Http 403 errors from my Asp.Net WebApi controllers when the user does not have permission to perform certain tasks.
However, I'd like to use a substatus on this to give further details about the error, along with the error message.
At the moment, what I get is
HTTP/1.1 403 Read access forbidden
but what I'd like to see is
HTTP/1.1 403.2 Read access forbidden
The code I'm using currently:
[HttpGet]
public EnrollmentDetail Details(int id)
{
var enrollmentDetail = _context.GetEnrollmentDetail(id);
if (!enrollmentDetail.R)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden)
{
ReasonPhrase = "Read access forbidden"
});
}
return enrollmentDetail;
}
I can't find any information any where on how to add these sub-statuses to the response. Is there any way it can be done with the built-in classes? If not, is there a way to write a custom HttpException which could do this for me?
That's because sub-statuses are not part of the HTTP spec and should not be used. If you want to send more details about the problem you encountered, take a look at Json-problem

Resources