MVC6 Prevent Redirect on unauthorized - angularjs

I'm developing an ASP.NET MVC 6 Web API app, with AngularJs frontend.
When I leave a session to decade, or I'm trying to call a Web API action unauthorized, I expect to receive a 401 status code.
Instead, I get a 302, and tries to redirect to the default path for login ("/Account/Login").
So I need to handle this in Angular.
From other forum posts here and googling I found that some people resolved their problems using in startup.cs:
services.Configure<CookieAuthenticationOptions>(options =>
{
options.LoginPath = PathString.Empty;
});
No luck for me.
I use Identity as authentication backend and even adding
services.ConfigureIdentityApplicationCookie(options =>
{
options.LoginPath = PathString.Empty;
});
does not give me the expected result. ASP.NET docs suggest this way to return a 401.
Using 1.0.0-beta7 CLR x86, IIS Express.

EDIT: the solution proposed by #EZI is correct.
Below my answer, which doesn't work on recent release.
Finally! I found the solution!
To be complete, I started with this comment found on source code in aspnet/Identity github.
// If the LoginPath is null or empty, the middleware will not look for 401 Unauthorized status codes, and it will not redirect automatically when a login occurs.
which give me the wrong directions.
Digging with debug on ConfigureIdentityApplicationCookie' options, I found that there is a delegate on "Notifications" property
OnApplyRedirect
Bingo!
Now I can control the redirect.
services.ConfigureIdentityApplicationCookie(options =>
{
options.LoginPath = PathString.Empty;
options.Notifications = new CookieAuthenticationNotifications {
OnApplyRedirect = context => { context.Response.StatusCode = 401; }
};
});
This maybe isn't a good way to handle the problem, but finally I receive a 401 Unauthorized when the web.api action is called without authentication.

For me it worked to just set the AutometicAuthenticate to false.
services.Configure<IdentityOptions>(options =>
{
options.Cookies.ApplicationCookie.AutomaticAuthenticate = false;
options.Cookies.ApplicationCookie.AutomaticChallenge = false;
options.Cookies.ApplicationCookie.LoginPath = PathString.Empty;
});

my solution was similar to #Ezi
Confirmed working for RC2
services.AddIdentity<IdentityUser, IdentityRole>(options =>
{
options.Cookies.ApplicationCookie.AutomaticChallenge = false;
});

Related

salesforce forcejs not getting refresh token

i am using forcejs in my angular app which is working fine and gives me accessToken. However, I am not able to get refreshToken to be able to renew accessToken as needed. The code is below
import { OAuth, DataService } from 'forcejs';
async loginSFDC(){
let callbackUrl = 'https://my.callback.url'
let oauth = OAuth.createInstance('client key','', callbackUrl);
oauth.login().then(
async (oauthResult) => {
DataService.createInstance(oauthResult);
console.log("Logged Into Salesforce Successfully:::" + JSON.stringify(oauthResult));
});
}
the above code is printing accessToken but no refreshToken. Please advise
i have also tried passing the 2nd parameter in createInstance as http://login.salesfoce.com?scope=full+refresh_token but that does not work as url gets constructed wrong on adding the scope=full+refresh_token
From looking at the source code of forcejs, you can use the refreshAccessToken() method with the DataService instance you created.
After some more debugging it is discovered that the refresh token shows up when my code is running on localhost but does not when it is deployed to the the webserver. i dont know how to debug further or fix it. but i have verified that this behavior is consistently reproducible

auth0 parseHash can't create property '__enableIdPInitiatedLogin' on hash string

I'm trying to upgrade my React web app from auth0-js 9.6.1 to 9.7.3. After installing the new library, my Slack login flow no longer works, it appears to be breaking in the callback.
TypeError: Cannot create property '__enableIdPInitiatedLogin' on string '#access_token={token string}&token_type=Bearer&state={state string}'
My parseHash call is:
this.auth0.parseHash(hash, (err, authResult) => {
if (authResult && authResult.idToken) {
AuthService.setToken(authResult.idToken); // JWT returned from Auth0;
// Redirect user to content.
const returnUrl = localStorage.getItem(Variables.RETURN_URL_KEY);
localStorage.removeItem(Variables.RETURN_URL_KEY);
returnUrl
? window.location.replace(returnUrl)
: window.location.replace("/");
} else if (err) {
console.log("Error with auth callback", err);
window.location.replace("https://foo.com"); // If auth fails, send user to home page.
}
}
This works fine in 9.6.1, but fails in 9.7.x and I can't find anything about any breaking changes that would cause it to start failing. Any ideas?
I had the same issue as you so I opened a ticket on the Auth0.js library github page.
This is the response I got from the developers:
It was working by accident then (also, the string is being ignored in your case), considering that we expect the first parameter to either be an object or a callback function.
All of our docs mention that:
https://github.com/auth0/auth0.js#api
https://auth0.github.io/auth0.js/global.html#parseHash
https://auth0.com/docs/libraries/auth0js/v9#extract-the-authresult-and-get-user-info
In your case, the simplest fix is to just remove the first parameter and keep only the callback. window.location.hash is already used when there's no options object.
(emphasis on the fix mine)
I tested 9.7.3 with this.auth.auth0.parseHash((err, result) => ... and it worked like a charm.
I hope this'll help!

Route param is getting weird

I have few routes in which i add token or id dynamically on user actions.
so the issue is dynamic params is turning weird and causing problem for my backend. some of buggy url mention below
/feedback/:token which changes to /feedback?token=%7B%7BcurrentSharingImage%7D%7D
this is the code which is causing this issue
Feedback.get({token: $routeParams.token})
.$promise
.then(feedback => {
$scope.feedbackDetails = feedback;
// remaining code
});
/download-file/:id which changes to /download-files/{{currentSharingImage}}
DownloadFile.getOne({id: $routeParams.id})
.$promise
.then((fileRequest) => {
}).catch(()=>{
$scope.control.isLoading = false;
Alert.errorToast('Error getting file.');
});
/hub-admin/manual-messaging/:id which changes to /hub-admin/manual-messaging/{{currentSharingImage}}
There are many URLs but I have came across this.
I am using angular 1.5.8 and specifically issue is with FireFox. Can I get some clue what is causing this issue?

OAuth2 with Satellizer and a generic OAuth2 provider

I'm having much trouble getting OAuth2 to work with a generic OAuth2 provider. Here's the situation.
A service provides an OAuth2 authentication method to where I want to authorize with. I've created an AngularJS app that has the following configuration for satellizer:
authProvider.baseUrl = 'http://localhost:3030/user/authorize';
$authProvider.oauth2({
name: 'customname',
url: '/token',
clientId: 'someapp',
requiredUrlParams: ['scope'],
scope: ['profile'],
authorizationEndpoint: 'http://location.to.oathserver',
redirectUri: 'http://localhost:3000'
});
The baseUrl points to my node server that should handle the middleware part.
I've also the following code that triggers the authentication part.
$scope.authenticate = function(provider) {
$auth.authenticate(provider)
.then(function(response) {
console.log(response);
})
.catch(function() {
//something went wrong
});
}
So far this all seems to work great and looks very similar to what is documented by Satellizer! Now once I start the angular app and start the authentication I see requests coming by that target my Node service.
Next I've my node.js service that hooks to the 'user/authorize/token' URL. Here's the code:
router.options('/authorize/token', function(req, res, next) {
//var token = req.header('Authorization').split(' ')[1];
res.end();
});
and:
router.post('/authorize/token', function(req, res, next) {
var authCode = req.param('code');
var cliendId = req.param('clientId');
var payload = jwt.decode(authCode, 'mySecret');
});
Here's where it all seems to go wrong. First I seem to get an OPTIONS request. I've not really an idea what to do with it as I can't seem to find anything in the documentation about an OPTIONS request. I thought it would might contain the 'Authorization' header but that doesn't seem the case so I close the connection with a res.end();
I also inspected the request in Chrome but I can't seem to find a header that has this exact name.
Next I get a POST request. This does seem to contain some things, hooray! I get the following object:
{
code: "ZFFeat9pWfHzw4rGmjFYwucPRMFnBOkd2odEObvo",
cliendId: "someapp",
redirectiUri: "http://localhost:3000"
}
This looks to me like the authorization code that I should have to decode. That's what you see me trying as well in the code above. Unfortunately this seems to throw me an error
Error: Not enough or too many segments
This tells me I'm doing probably something wrong, and I got stuck.
I do have some PHP code that seems to work for someone else but I don't fully understand and can't really relate the code to my code since PHP is not my speciality and node.js/JavaScript not his. So here goes the PHP code:
handle_cors(); // Handle CORS for cross domain requests
// Get JSON data
$input = json_decode(file_get_contents("php://input"), true);
// Create Provider
$provider = new SomeApp\OAuth2\Client\Provider\SomeApp([
'clientId' => 'someapp',
'clientSecret' => 'mySecret',
'redirectUri' => $input['redirectUri'],
]);
// Optional: Now you have a token you can look up a users profile data
try {
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $input['code']
]);
// We got an access token, let's now get the user's details
$user = $provider->getResourceOwner($token);
header('Content-Type: application/json');
$result = $user->toArray();
$result['token'] = create_token('my-example-key', $user->getId());
echo json_encode($result);
exit();
} catch (Exception $e) {
// Failed to get user details
exit('Oh dear...' . $e->getMessage());
}
Hopefully someone can help me out! Thanks in advance.
Sorry guys, I've been able to solve it myself. I found out that I was missing some URL's to POST to and GET from. After that the examples from Satellizer became clear and was able to use them almost as a carbon copy.

Unknown Reason for JWT Tokens invalidation

I'm facing very weird problem with my laravel-Angular application. I'm using Tymon JWT to refresh token on my every request. I'm using Satellizer library to handle these JWT-Tokens, however, Satellizer doesn't seem to have a response interceptor to capture the new token. Hence I wrote my own Interceptor to do so.
.factory('ResponseHttpInterceptor', function ($window) {
return {
response: function (response) {
if (response.headers('Authorization') != null) {
$window.localStorage.removeItem('satellizer_token');
$window.localStorage.setItem('satellizer_token', response.headers('Authorization').replace('Bearer ', ''));
}
return response;
}
}
})
This code basically captures the new token and replaces the existing token in local storage with the new token.
My test flow is:
Login -> Make who Am I call -> Logout
Upon Logout I receive an error Invalid token (this doesn't happen always. Sometimes the flow succeeds and sometimes it fails). This flow works perfect via REST Client postman. So I don't think there is any problem in my API's
Attaching image showing the new token being passed, after it is refreshed after my whoami call.
Upon logout I'm clearing the local storage. Can Anyone tell me what could be the reason for this?
EDIT
Route::group(['prefix' => 'api/v1_0'], function () {
Route::post('login', 'Auth\AuthControllerGeneral#postLogin');
Route::get('logout', ['middleware' => 'jwt.auth', 'uses' => 'Auth\AuthControllerGeneral#getLogout']);
Route::group(['middleware' => ['jwt.refresh', 'jwt.auth']], function() {
Route::get('whoami', 'Auth\AuthControllerGeneral#loggedInUserInfo');
});
});
Check you htaccess you should have below code there
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
And AuthContrller is same as https://github.com/sahat/satellizer/blob/master/examples/server/php/app/Http/Controllers/AuthController.php
And Some people forget to check Authenticate middleware. Check this also
https://github.com/sahat/satellizer/blob/master/examples/server/php/app/Http/Middleware/Authenticate.php
I suggest first try with default route as in demo
https://github.com/sahat/satellizer/blob/master/examples/server/php/app/Http/routes.php
And still you not get the solution then try with sample client end folder.
https://github.com/sahat/satellizer/tree/master/examples/client
Which you can put in your laravel public folder just to test.
I found everything working fine in satellizer but some people fails in configuring this.

Resources