Base solution for your next web application
Open Closed

AbpAuthorization stuck in a infinite loop!? #85


User avatar
0
gvb created

I'm trying to secure my ApplicationService now,

i checked ModuleZeroSample and tried to do the same but something must be wrong in my code... but i doesn't find the problem :(

When i try to go in a protected route... i have a Popup that say "No user logged in!" with an ok button ? when we click ok it reload the same page.... so there is the infinite loop ?!

What am i doing wrong ?

I did the same for my ParticipantList and this one work i have the same exact code for the client and still the client doesnt work at all.... And my ParticipantList doesnt send his RequestURL to the Login page... so when the user is connecting he doesn't get redirected to the page he was trying to get.

I know it work on sample of Zero Module but i dont know what i'm doing wrong ..!

Thx for the help in advance :)

Application Service

[AbpAuthorize]
    public class GetClientListService : ApplicationService, IGetClientListService

AuthorizationProvider

public class SurveyAuthorizationProvider : AuthorizationProvider
    {
        public override void SetPermissions(IPermissionDefinitionContext context)
        {
              // No Need for special permission at the moment, just to be connected
        }
    }

ApplicationModule

[DependsOn(typeof(SurveyCoreModule))]
    public class SurveyApplicationModule : AbpModule
    {
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
            Configuration.Authorization.Providers.Add<SurveyAuthorizationProvider>();
            Configuration.Settings.Providers.Add<SurveySettingProvider>();
        }
    }

Startup class in WebProject

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });

            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        }
    }

AccountController

[HttpPost]
        public async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "")
        {  
            //     ... login validation ....

           if (string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = Request.ApplicationPath;
            }

            return Json(new MvcAjaxResponse { TargetUrl = returnUrl });

        }

14 Answer(s)
  • User Avatar
    0
    gvb created

    I tried to put AbpAuthorize Attribute over my HomeController and still he doesn't do anything.... he still show me a my _layout.cshtml but it shouldn't ?! it should do like in SampleZero and redirect me to the Account/Login MVC Path...

    What did i miss to make AbpAuthorize working ??

    the documentation doesn't tell anything else than how to put the attribute with permission but doesn't talk about the redirect and what really need to be done to make it work :S and i dont see diference between moduleZeroSample and my project!

    [AbpAuthorize]
        public class HomeController : SurveyControllerBase
        {
            public ActionResult Index()
            {
                return View("~/App/Main/views/layout/layout.cshtml");
            }
    	}
    
  • User Avatar
    0
    hikalkan created
    Support Team

    Infinite loop is normal. Let's explain why:

    When you make an AJAX call (a dynamically created web api for an application service for your situation), abp.js (or abp.ng.js if you're using angular) makes the call and checks the result. If your result says that there is an authentication error, it refresh the page. Why refresh?

    Normally, an AJAX call made for a click or another action taken by user. If this action is not authorized, you don't allow user to perform this action. Say that you have a 'delete task' button and user has not delete task permission. So, why did you show this button? This is a programmer error. This should not be happen. But, maybe session timed out while user in the page. In this case, you got a authorization error from server. Refreshing page makes us redirect to login page normally. But, for your situation, you probably did not authorize the page itself.

    I hope I could tell the reason :) Actually, it's simple: Don't allow user to perform unauthorized task in the client side. Another example: Say that user has 'delete task' permission when he entered the page. Then we removed this permission from user from another browser. What if the user clicks the button. He gots an auth error. Refreshing page allow us to re-check permission and do not render the button.

  • User Avatar
    0
    gvb created

    hmmm it seem's strange to me! because your ModuleZeroSample work as i want ... if i try to access a page that have an AbpAuthorize i got redirected to the Login Page!

    Why i dont get this with my AbpAuthorize....

    OR how do i protect my page from being accessed by user that he doesn't have access like

    mysite.com/#/client/list <--- Required User to be Connected!

    in my system you only need to be connected to check the client list, so if u enter the URL manually or save the page in ur favorite, i just want you to be redirected to login page then to the page back when you are connected!

    I dont have any Button with an action that appear and shouldn't

  • User Avatar
    0
    hikalkan created
    Support Team

    Actually, it's simple!

    check <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/blob/master/sample/ModuleZeroSampleProject.Web/Controllers/HomeController.cs">https://github.com/aspnetboilerplate/mo ... troller.cs</a>

    As you see it has AbpMvcAuthorize attribute to check if user is authenticated. If not, it's redirected to login page. You can use such a controller action to get angular view (probably the layout as here).

  • User Avatar
    0
    gvb created

    And how do i control, because if i put the AbpMvcAuthorize, it will ask authentication for all my route ? no ?

    mysite.com/#/client/list <-- Require authentication mysite.com/#/news/create <-- Require authentication mysite.com/#/news <-- Doesn't require authentication mysite.com/#/project <-- Doesn't require authentication

    Thx for your help, it help a lot ! :)

  • User Avatar
    0
    gvb created

    so any idea on how to protect route ? or WebAPI route!?

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    You should conditionally build route like that:

    if(haspermission-1) { defing route-1 } ...

    This prevent user to go to the route by hand. Did you asked that?

  • User Avatar
    0
    gvb created

    no

    What i'm asking for is :

    I want to protect my route to redirect to login page if login or any permission is required and the person is not connected. If the person is connected and doesn't have the permission i need to make the person back to the home page.

    so mysite.com/#/client/list is a route that need to be connected to access it, but the person can be offline and try to enter this URL. I need abp to catch the exception of no authorization and redirect to the login. (if person is not connected) or if the person is connected and doesnt have the permission redirect him to the home page or page that i can specifie.

    i dont know if you understand a bit more now ?

    But i like a lot what you said about route, i will protect the route as you said!

    But do you know how to add or remove route depending on connection state?

  • User Avatar
    0
    hikalkan created
    Support Team

    Sorry but I could not understand what you mean saying "person is connected". You mean "logged in?" or "connected to internet?".

  • User Avatar
    0
    gvb created

    Connected = Logged In! :)

    sorry i'm not native english so i'm trying my best ^^

    But i did a brainstorming on what you said about the route if the person is not LoggedIn, i shouldn't add the route to AngularJS.

    I found this Post about dynamic route in AngularJS <a class="postlink" href="http://stackoverflow.com/questions/13153121/how-to-defer-routes-definition-in-angular-js">http://stackoverflow.com/questions/1315 ... angular-js</a>

    So i will protect my route by this when the person log in, i will add route and if he disconnect i will remove route depending on permission and role.

    But still the same question remain if the person session end while he is in a page that required to be logged in, i need the WebApi answer to redirect me to login page with my current URL so i get redirected back where i was before log in.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    When a user logouts (disconnects) you should not (may be can not) remove Angular routes, just send him to out of the SPA, to the login page which is not even AngularJs application. So, also, when user in the page and session timed out, then he will get an authorization error in first web api call. ABP automatically refresh the page. In this time you should redirect user to login page (this can be automatically done if your Angular layout is retrieved using an MVC controller which has Authorize attribute).

    Example project does it: <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero/tree/master/sample">https://github.com/aspnetboilerplate/mo ... ter/sample</a> Login page has different Layout then Angular application. You can check & test it.

  • User Avatar
    0
    gvb created

    half of my angular route doesn't require the user to be logged in. that's why i doesn't want to put the AbpMvcAuthorize over my homecontroller

    there is no other alternative?

    we did some change in the source code but we cannot update the project easily each patch of ABP... and it may broke if you change something core ....

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    All redirection is done in abp.ng.js (<a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/blob/master/src/Abp.Web.Resources/Abp/Framework/scripts/libs/angularjs/abp.ng.js">https://github.com/aspnetboilerplate/as ... /abp.ng.js</a>):

    if (originalData.unAuthorizedRequest && !originalData.targetUrl) {
                                    if (messagePromise) {
                                        messagePromise.done(function () {
                                            location.reload();
                                        });
                                    } else {
                                        location.reload();
                                    }
                                }
    

    You can modify here for your needs. You can remove location.reload and redirect to home page. This is workaround for now. I'll provide a way of overriding this behaviour. See <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/issues/486">https://github.com/aspnetboilerplate/as ... issues/486</a>

  • User Avatar
    0
    gvb created

    Thanks a lot!

    This is the exact place where we modified your code source :)