Why are cookies unrecognized when a link is clicked from an external source (i.e. Excel, Word, etc...)
Asked Answered
I

18

82

I noticed that when a link is clicked externally from the web browser, such as from Excel or Word, that my session cookie is initially unrecognized, even if the link opens up in a new tab of the same browser window.

The browser ends up recognizing its cookie eventually, but I am puzzled as to why that initial link from Excel or Word doesn't work. To make it even more challenging, clicking a link works fine from Outlook.

Does anybody know why this might be happening? I'm using the Zend Framework with PHP 5.3.

Ichthyoid answered 16/4, 2010 at 14:23 Comment(2)
I think this question has no relation to frameworks nor sessions and even php. But more browser related. What browser do you use and have you tried any other? Does it send any cookie?Kimberlite
This happens in IE8, Chrome, and I believe Firefox. On debugging, it appeared that either no cookie was being sent or a new one was being created - I couldn't confirm it. But I am sure the correct cookie wasn't sent.Ichthyoid
P
98

This is because MS Office is using Hlink.dll component to lookup if the link is Office document or something else. MS Office expect to open the document linked within documents without the aid of external browser (using Hlink.dll component of IE6).

If session cookie protects website Hlink naturally is being redirected to login page and having reached HTML page and not able to "understand" it opens it in external browser. Note that it opens not original URL (expected behavior) but the result of redirect, even if it was 302 redirect.

Microsoft has that bug in unsupported component (Hlink.dll), instead of recognizing the bug they turn it over to our head (trying to convince us that it is flaw of SSO system we use, i.e. session cookies) and refuses to upgrade it. It offers workaround that turns off the lookup functionality of MS Office:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
  Office\9.0\Common\Internet\ForceShellExecute:DWORD=1

Or offer us to workaround serverside, to avoid HTTP redirects and change into Javascript redirects or META REFRESH redirects (i.e. to have Hlink get text/html page on original URL and make it run external browser to handle it).

Pilliwinks answered 29/4, 2010 at 11:21 Comment(11)
Thanks for this. I've been completely stumped by this behavior. Every other office application lets us paste links to our app no problem but MS office gets the login page every time.Ipoh
Thanks, it helped me out! You have the link there but I will enter this anyway. For a 32 Bit version of Office on 64 bit version of Windows the key is HKLM\SOFTWARE\Wow6432Node\Microsoft\Office\9.0\Common\Internet\ , and yes, it's still 9.0 also for MS Office 2013Camarillo
How evil of them to try to blame this on the SSO.Golgi
Can someone update this for the latest Microsoft Office ?Thormora
That 9.0 registry path applies to all versions of Office. The only change is wow6432node as noted above if you are using 32-bit Office.Myronmyrrh
In Office 2016 you have to use the right version - but create the same keyFrogman
OK so problem lies in MS Office, but I don't quite understand the answer. With Fiddler I see that Office (through the browser) is sending a nice GET request. Except that Accept-Encoding: gzip, deflate might be the problem?Threesome
So 11 years of breaking SSO later, this still hasn't been fixed. I found this answer after hitting this problem today, having no memory that I had faced this years ago and had even left a comment right here.Myronmyrrh
@AmitNaidu I can't find this 9.0 registry path neither in \SOFTWARE\Microsoft\Office\ nor \SOFTWARE\Wow6432Node\Microsoft\Office\ do you know if it has changed?Noli
@Noli Yes you wont find it, you have to create it.Myronmyrrh
For reference, here is the Microsoft link: learn.microsoft.com/en-us/office/troubleshoot/… . "If the SSO system exclusively relies on session cookie information, the SSO system may not appear to work because the same user moves from more than one session. This behavior is a fundamental design limitation of an SSO system when the SSO system is not designed to support SSO authentication across more than one browser". WAT?Fae
A
22

Server side this worked for me in IIS (using a rewrite rule)

<rule name="WordBypass" enabled="true" stopProcessing="true">
    <match url=".*" />
    <conditions>
        <add input="{HTTP_USER_AGENT}" pattern="Word|Excel|PowerPoint|ms-office" />
    </conditions>
    <action type="CustomResponse" statusCode="200" statusReason="Refresh" statusDescription="Refresh" />
</rule>
Almire answered 5/5, 2016 at 15:34 Comment(4)
This was quick and easy fix for my MVC5 app. I customized the pattern as needed. Note that this requires Microsoft Url Rewrite software to be installed on the web server. iis.net/downloads/microsoft/url-rewriteFogbound
Better in IIS to correct this behavior than the app itselfPenelopa
This worked like a charm on my ASP.Net 4.5 Web form applications. Thanks a ton! @MartinNotarize
I placed the code in the application's web.config file, and it works excellent.Linebreeding
Z
19

We had this same problem and wrote an open source gem to help those using rails: https://github.com/spilliton/fix_microsoft_links

You can use the same approach we used on any framework though:

  1. Detect if the user agent is from a Microsoft product
  2. Render a blank html page with a meta refresh tag that will cause the browser to refresh the page with the correct cookies

Example code here: https://github.com/spilliton/fix_microsoft_links/blob/master/lib/fix_microsoft_links.rb

Zlatoust answered 8/5, 2012 at 19:28 Comment(3)
This gem is a great solution.Slily
Man, thank you so much for this. I used your code to build a middleware for express.js github.com/auth0/fix-office-linkNonalignment
No problem! Glad it proved useful :)Zlatoust
I
10

PHP solution:

This prevents the MS product recognising the redirect. MS therefore launches a browser from the required link.

if (isset($_SERVER['HTTP_USER_AGENT']))
{
    $http_user_agent = $_SERVER['HTTP_USER_AGENT']; 
    if (preg_match('/Word|Excel|PowerPoint|ms-office/i', $http_user_agent)) 
    {
        // Prevent MS office products detecting the upcoming re-direct .. forces them to launch the browser to this link
        die();
    }
}

.. redirect after this code

Indirection answered 29/7, 2015 at 8:56 Comment(2)
This still worked for me in 2021. I was having the issue with Excel links but Power Point was working fine.Golgotha
This worked great for a MediaWiki installation by just adding it to LocalSettings.php.Fey
S
7

Fix for VB.NET:

Dim userAgent As String = System.Web.HttpContext.Current.Request.UserAgent

If userAgent.Contains("Word") Or userAgent.Contains("Excel") Or userAgent.Contains("PowerPoint") Or userAgent.Contains("ms-office") Then
       System.Web.HttpContext.Current.Response.Clear()
       System.Web.HttpContext.Current.Response.Write("<html><head><meta http-equiv='refresh' content='0'/></head><body></body></html>")
       System.Web.HttpContext.Current.Response.End()
End If

It basically forces the browser to refresh the page, so the request comes in with the user agent of the browser and all the correct cookies.

Smokeproof answered 20/2, 2014 at 10:59 Comment(0)
E
6

Here is a solution for C# ASP.NET based on spilliton's answer above. In Global.asax.cs, add the following:

    private static string MSUserAgentsRegex = @"[^\w](Word|Excel|PowerPoint|ms-office)([^\w]|\z)";
    protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
    {
        if (System.Text.RegularExpressions.Regex.IsMatch(Request.UserAgent, MSUserAgentsRegex))
        {
            Response.Write("<html><head><meta http-equiv='refresh' content='0'/></head><body></body></html>");
            Response.End();
        }
    }
Evoke answered 24/7, 2015 at 19:35 Comment(1)
I would also add a check if request is authenticated before checking for regex. Matching a userAgent against a regex on every request can lead to performance issues.Hesler
M
3

Here is an example of the fix using a dotnet core middleware:

public class MicrosoftOfficeLinksHandlingMiddleware
{
    private static readonly Regex MsUserAgentsRegex = new Regex(@"[^\w](Word|Excel|PowerPoint|ms-office)([^\w]|\z)");
    private readonly RequestDelegate _next;

    public MicrosoftOfficeLinksHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        string userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();

        if (userAgent != null && MsUserAgentsRegex.IsMatch(userAgent))
        {
            // just return an empty response to the office agent
            return;
        }

        await _next(context);
    }
}
Mellins answered 11/4, 2019 at 11:45 Comment(0)
E
2

1.From excel/word point to http://example.com/from_excel.php

2.In "from_excel.php" redirect to page where you use session

<script>document.location.href = "http://example.com/page_with_session.php"; </script>
Exchequer answered 31/1, 2014 at 10:56 Comment(0)
T
2

Here is how to workaround this with Java and Spring via a Filter:

/**
 * To see why this is necessary, check out this page:
 * https://support.microsoft.com/en-gb/help/899927.
 */
public class MicrosoftFilter extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(final HttpServletRequest request,
      final HttpServletResponse response,
      final FilterChain filterChain) throws ServletException, IOException {
    //Serve up a blank page to anything with a Microsoft Office user agent, forcing it to open the
    //URL in a browser instead of trying to pre-fetch it, getting redirected to SSO, and losing
    //the path of the original link.
    if (!request.getHeader("User-Agent").contains("ms-office")) {
      filterChain.doFilter(request, response);
    }
  }
}

/**
 * Security configuration.
 */
@Configuration
public class SecurityConfiguration {
  @Bean
  public FilterRegistrationBean microsoftFilterRegistrationBean() {
    FilterRegistrationBean<MicrosoftFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new MicrosoftFilter());
    registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return registrationBean;
  }
}
Tippet answered 24/8, 2018 at 7:6 Comment(1)
First of all, I can't believe I even found this question... nice that there are solutions given for so many platforms... but Java is the one I needed... Thanks everyone!Throughcomposed
L
2

We are seeing a problem that TWO Chrome tabs are opened when clicking an URL from MS Word, and the page to open has JavaScript redirection: window.location.href=blabla

By debugging from the servers side, we confirmed that there are requests sent from Office app, besides Chrome. This is so wierd.

But anyway, by checking the request header "User-Agent", and returning an empty page to Office apps, our TWO tabs issue got resolved. That's definitely the right thing to do!

Landahl answered 29/10, 2018 at 15:21 Comment(1)
What User-Agent are you seeing from Office apps?Behr
L
2

NGINX solution below:

if ($http_user_agent ~* Word|Excel|PowerPoint|ms-office) {
    return 200 '<html><head><meta http-equiv="refresh" content="0"/></head><body></body></html>';
}

You can put it in the server or location block. Works like charm.

Lunalunacy answered 2/10, 2019 at 0:47 Comment(0)
T
1

Here is my solution for this in WordPress. Add this to functions.php in your theme or another plugin file.

This may be helpful if your system, like WP, sends logged out users to a login page with a redirect to the page they were trying to access. Word was sending users to this page, but then WP wasn't properly handling the case where a user was already logged in. This code checks if there is a current user and a redirect_to param passed. If so, it redirects to the redirect_to location.

function my_logged_in_redirect_to()
{
global $current_user;

if($current_user->ID && $_REQUEST['redirect_to'])
{           
    wp_redirect($_REQUEST['redirect_to']);
    exit;
}
}
add_action('wp', 'my_logged_in_redirect_to');
Tanyatanzania answered 28/5, 2011 at 15:49 Comment(0)
V
1

Here's a VBA fix, for Excel. The same concept can be applied for Microsoft Word. Basically, rather than firing off the link from within Excel, the code executes the link from within a shell. Here's the code:

Private Sub Worksheet_FollowHyperlink(ByVal objLink As Hyperlink)
    Application.EnableEvents = False
    Dim strAddress As String
    strAddress = "explorer " & objLink.TextToDisplay
    Dim dblReturn As Double
    dblReturn = Shell(strAddress)
    Application.EnableEvents = True
End Sub
  1. For the Excel sheet that contains the links, right-click the sheet tab and click View Code. The VBA editor appears.
  2. Paste the code into the window, and close the editor.
  3. Modify each link in the page so it simply points back to the cell that it is in. To do so:
  4. Right-click the link, and click Edit Hyperlink. An Edit Hyperlink window appears.
  5. Click Place In This Document.
  6. Click the sheet name.
  7. For Type the cell reference, enter a cell reference (e.g. A4).
  8. Click OK.

A couple of notes:

  • You will need to save the spreadsheet as a macro-enabled spreadsheet (.xlsm). When users open the spreadsheet, they will be asked to enable macros. If they answer No, the links will not work.
  • These instructions are based on Excel 2010. Presumably later versions are similar.
Vogeley answered 24/1, 2017 at 21:22 Comment(1)
Presumably, on OS X, this would need to use 'open' instead of 'explorer'... or would this method even work on a Mac?Windowpane
T
1

I can't believe they call this a feature. However, here's a featurefix for Apache:

RewriteEngine On

# Send a 200 to MS Office so it just hands over control to the browser
# It does not use existing session cookies and would be redirected to the login page otherwise
# https://www.wimpyprogrammer.com/microsoft-office-link-pre-fetching-and-single-sign-on/

RewriteCond %{HTTP_USER_AGENT} ;\sms-office(\)|;)
RewriteRule .* - [R=200,L]

Might not be best performance wise, as the whole page gets sent instead of an empty response, but I did not want to add another Apache modules just for fixing such an idio^H^H^H^H feature.

Tushy answered 8/6, 2018 at 7:53 Comment(0)
M
0

I had to solve this issue for an ASP.NET site but I only wanted to use javascript/ jQuery:

var isCoBrowse = ('<%= Session["user"].ToString().ToLower() %>' != '0');
if (isCoBrowse && window.location.href.indexOf('ReturnUrl=') >= 0 && window.location.href.indexOf('dllCheq') == -1) {
    //redirect to the ReturnUrl & add dllCheq to the URI
    var toRedirect = decodeURIComponent(gup('ReturnUrl', window.location.href)) + '&dllCheq';
    window.location = toRedirect;
}

I got the gup function from: How to get the value from the URL parameter?

Mansfield answered 28/10, 2015 at 13:32 Comment(0)
U
0

Use fix provided by microsoft given link below. https://support.microsoft.com/en-us/kb/218153

Unclog answered 3/11, 2015 at 8:33 Comment(1)
this link was already mentioned in the accepted answer. Furthermore, the solution suggested here has dramatic repercussions on linking functionality across all Office products.Lizabethlizard
T
0

And in ColdFusion / Lucee

<cfif cgi.HTTP_USER_AGENT contains "Excel" OR cgi.HTTP_USER_AGENT contains "ms-office">
    <cfabort/>
</cfif>
Tacitus answered 22/2, 2021 at 20:24 Comment(0)
F
-1

I suspect this is a matter of how you are setting the cookie(s).

Due to the nature of how the web was created, example.com is not seen as the same domain as www.example.com; hence: you can be logged in at www.example.com and not logged in at example.com.

So in other words, check the URL in your word or excel file - is it the same domain as how you are logged in within your browser?

There are two fixes/solutions to this cookie inconsistency: 1. redirect anyone who tries to load your site without the www. to the same page with the www. (or vice versa), or 2. when you are setting the cookie, make sure to specify the domain argument as ".example.com". The leading dot indicates the cookie should be valid on all subdomains of that domain as well.

I suspect the reason the browser eventually recognizes it is because you probably eventually end up landing on a URL with the same domain structure as how you are logged in.

Hope this helps.

Fanciful answered 18/4, 2010 at 14:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.