Developer forum

Forum » Development » Log user in via code

Log user in via code

Kasper Legarth
Reply

Hello.

I have a client-side fetch to an internal page. That page includes af ICC app i use to get some specific information from BC.
I tried to log the user in via the API before calling the internal page. I get the token from the first call but the call to the ICC app still returns "No user logged in"

Have anyone done anything similarly? 


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Kasper

Can you share little more context? What is the internal page?

I guess you login the user on the webapi using authenticate and getting back the JWT token?

How do you fetch the page? Using a regular URL (hitting the pageview?).

That would be mixing 2 different pipelines that do not authenticate the same way. 

If you are getting the page from the webapi as well, it will not be able to return the contents of the ICC app.

BR Nicolai

 
Kasper Legarth
Reply

Hi Nicolai.

More context: The user visits a product page. Where you can buy the product in single pieces or in bundles. To Bundle look up take quite a while. So we fetch that async after internal page load. I fetch them through standard fetch in javascript. (In this case vue.js)

 

                    let requestUrl = `/Default.aspx?ID=1100&ICC_itemId=${productNo}`;

                    fetch(requestUrl)
                    .then(response => response.json())
                    .then(response => {
                         ...
                    })

 

The page I'm fetching is has an ICC app as content with this template:


@{
    int x = 0;
    bool hasPages = !String.IsNullOrWhiteSpace(GetString("Ecom:IntegrationCustomerCenter.Paging.HasPages")) ? true : false;
    string nextPage = "";
    if(hasPages && GetInteger("Ecom:IntegrationCustomerCenter.Paging.CurrentPage") < GetInteger("Ecom:IntegrationCustomerCenter.Paging.NumPages")) {
        nextPage = GetString("Ecom:IntegrationCustomerCenter.Paging.Forward.URL");
    }
}
{
    "bundleCount": @GetLoop("Ecom:IntegrationCustomerCenter.BundleLoop").Count(),
    "nextPage": "@nextPage",
    "currentPage": @GetInteger("Ecom:IntegrationCustomerCenter.Paging.CurrentPage"),
    "bundles": [
        @foreach(var bundle in GetLoop("Ecom:IntegrationCustomerCenter.BundleLoop")) {
            x++;
            if(x > 1) {
                <text>,</text>
            }
            <text>
                {
                    "bundleNo": "@bundle.GetString("BundleNo")",
                    "thickness": "@bundle.GetString("Thickness")",
                    "length": "@bundle.GetString("Length")",
                    "width": "@bundle.GetString("Width")",
                    "stock": {
                        "warehouse": "@bundle.GetString("Stock")",
                        "sea": "@bundle.GetString("StockSea")",
                        "units": "@bundle.GetString("StockUnits")",
                        "seaUnits": "@bundle.GetString("StockSEAUnits")"
                    }
                }
            </text>
        }
    ]
}

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

So I guess the user is already logged in on the page - otherwise you need to do that of course.

Then remember that fetch will not send over credentials - and that also no cookies - meaning that asp.net session cookie is not send as part of your fetch request and DW sees it as anonymous.

So you need to enable credentials and ensure cookies are send with the fetch request - then DW will recognize the user:

https://developer.mozilla.org/en-US/docs/Web/API/fetch

BR Nicolai

 
Kasper Legarth
Reply

Yes that is correct, if no user is loggedin. We have a fallback user for annonymos users. 

Would it be better to move the login check and login to the template with the ICC so it is not through the API?

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

As I mentioned, the webapi login returns a JWT token that will not work for regular pages.

So you have to ensure you are authenticated on the page and that you send cookies on your fetch requests.

 
Kasper Legarth
Reply

Do I misapprehend what your are saying? Should'nt just ensure that credentiels/cookes are sendt in the fetch with the credentials setting? Or do I miss some other steps?

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Probably

  1. A user goes to the website and logon to the site - the site now knows who the user is. (You cannot login using the webapi)
  2. In your dev tools you can see that asp.net session cookie
  3. Create a fetch request to the ICC page and ensure that you can see all cookies being send as part of the request (Check that in dev tools)
  4. Then your ICC page should be executed in the context of the user

BR Nicolai

 
Kasper Legarth
Reply

Hi Nicolai.

Ahh okay, i had it the other way around in my head.
So my problem is actually trying to log a user on with the webapi. Is there a way the log a user in through code?

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply
This post has been marked as an answer

Create an instance of Dynamicweb.Frontend.LogOnHandler and call Logon with username and password.

Alternatively send the username and password as part of a post to the ICC page.

Votes for this answer: 1
 
Kasper Legarth
Reply

Hi Nicolai. 

Thank you for all your help. I ended up sending the credentials in the post. It gave the best (for me) solution.

 
Kasper Legarth
Reply

Hi @Nicolai.

Sorry for trolling up in an old post. Do you happen to know if this feature has been removed?
The services I build now return "no user logged in" even though I send a username and password. It worked like a charm some months ago.

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

I do not think we deprecated anything.

Can you tell me what exactly you are trying - maybe show some code or requests?

 
Kasper Legarth
Reply

A little context:

Our customer has some product information that we request from the frontend after initial page load. We do this because it can be quite a heavy task.
The customer's BC partner have made a new endpoint, so vi kan use the ICC app to get the information. That means I have set up an ICC app that returns json when fetched. 

If I fetch the app when not logged in, it just returns "No user logged in" it never tries to contact BC. Earlier I fixed this with your solution and added username and password for a dummy user.

My request is a simple javascript fetch: 


lookUpBundle: async function(productNo, url) {
    this.loadingBundles = true;
    let requestUrl = `@(BundleLookup)&ICC_itemId=${productNo}`;
    if(url && url != "") {
        requestUrl = url;
    }
    if(!this.isLoggedIn) {
        if(requestUrl.indexOf('username') < 0) {
            requestUrl += '&username=mailtest@gotcha.dk&password=K123456';
            this.tempLoggedIn = true;
        }
    }
    fetch(requestUrl, {
        credentials: "same-origin"
    })
    .then(response => response.json())
    .then(response => {
  ...
  }
}

The ICC app. uses this template:


@{
    int x = 0;
    bool hasPages = !String.IsNullOrWhiteSpace(GetString("Ecom:IntegrationCustomerCenter.Paging.HasPages")) ? true : false;
    string nextPage = "";
    if(hasPages && GetInteger("Ecom:IntegrationCustomerCenter.Paging.CurrentPage") < GetInteger("Ecom:IntegrationCustomerCenter.Paging.NumPages")) {
        nextPage = GetString("Ecom:IntegrationCustomerCenter.Paging.Forward.URL");
    }
}
{
    "bundleCount": @GetLoop("Ecom:IntegrationCustomerCenter.BundleLoop").Count(),
    "nextPage": "@nextPage",
    "currentPage": @GetInteger("Ecom:IntegrationCustomerCenter.Paging.CurrentPage"),
    "bundles": [
        @foreach(var bundle in GetLoop("Ecom:IntegrationCustomerCenter.BundleLoop")) {
            x++;
            if(x > 1) {
                <text>,</text>
            }
            <text>
                {
                    "bundleNo": "@bundle.GetString("BundleNo")",
                    "thickness": "@bundle.GetString("Thickness")",
                    "length": "@bundle.GetString("Length")",
                    "width": "@bundle.GetString("Width")",
                    "stock": {
                        "warehouse": "@bundle.GetString("Stock")",
                        "sea": "@bundle.GetString("StockSea")",
                        "units": "@bundle.GetString("StockUnits").Replace(",", "")",
                        "seaUnits": "@bundle.GetString("StockSEAUnits")"
                    }
                }
            </text>
        }
    ]
}

This used to work. And to my knowledge, the only thing that has changed is we updated the solution to 9.15.8.

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Just checked our login code and it has no changes in 238 days.

Can I see the actual request in your network tab on your browser developer tools?

You have this conditional: 

if(!this.isLoggedIn) {

Which looks a bit odd... Not that I fully understand the context.

BR Nicolai

 
Kasper Legarth
Reply

it is a variable in my vue.js application that knows If a user is logged in. If not i need to add a username and password to the request.

I have attached the request.

screen1.png
 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply
This post has been marked as an answer
From your screendump I can see that &expires=true is appended to the URL. That happens if password expiration feature is enabled and the password has expired for a given username. You need to give the user a new password or disable the expiration feature. /Morten
Votes for this answer: 1
 
Kasper Legarth
Reply

Hi Morten. You are right.

That was also my initial thought. My problem was that I tried to reset the default users password to the same as before, and didn't release my mistake. 

Nicolai and Morten, thanks a lot for your help :)

 

 

You must be logged in to post in the forum