0

I have two Asp.Net Core MVC apps and login system on IdentityServer4. First app is fully protected, means all controllers are behind [Authorize] attribute and that one works fine. Second app is public app and has no any [Authorize] attributes.

Issue is on second app on line

@if (User.Identity.IsAuthenticated)
{
    <a href="#">@User.Identity.Name</a>
}

because User.Identity.IsAuthenticated is always false. This piece of code is on razor page which is called from simple action

public IActionResult Index()
{
    return View();
}

What I figured out is when I add [Authorize] attribute on this action then there is call to IDS4 'connect/authorize' endpath and User.Identity.IsAuthenticated is authenticated and all works fine.

Trouble is that action should be without [Authorize] attribute and I just want to show user name and/or user email if user is logged in.

Is there any other way to verify cookie and get user info in User.Identity?

jannowitz
  • 84
  • 7
  • 1
    this is not identityserver specific. and [here](https://stackoverflow.com/questions/49328660/sharing-cookies-between-two-asp-net-core-applications) is the answer – d_f Jul 23 '19 at 15:33
  • It makes no sense to show the name of the user when the user didn't login. If the problem is that the site had to be accessable for anonymous users, simply add a login button that triggers the login. Being already authenticated by IdentityServer the user will automatically be logged in. And this also allows the user to logout, like any other app. – Ruard van Elburg Jul 23 '19 at 20:44

2 Answers2

0

You must have the Authorize attribute applied to have User populated. Period. If you don't want to actually restrict access, you can add also the AllowAnonymous attribute. Generally, the best approach is to decorate all controllers that involve users with [Authorize], and then selectively allow access for specific actions using [AllowAnonymous].

Chris Pratt
  • 207,690
  • 31
  • 326
  • 382
  • I guess, you missed the idea. The OP just wanted to get the Id of a user by the fortune logged in *to the other app*. (if I caught it correctly :) Nevertheless your point about combining the attributes has sense. That performs `AuthenticateAsync()` and skips `AuthorizeAsync()`. So the OP has to perform two steps: share the cookie, starting from `DataProtectionProvider` and call `AuthenticateAsync()` to populate the identity when exists – d_f Jul 23 '19 at 18:52
  • Sharing cookies could be a problem, but since Identity Server is involved, both apps should be able to authenticate independently. The main auth cookie is from the ID4 server. The issue seems to be simply that this second site is a public site, that doesn't require authentication, so the Authorize attribute was not being employed at all. – Chris Pratt Jul 23 '19 at 19:27
  • In this case, assuming a public site, only a Login button (calling a secured method) would suffice. That'll at least give the user the choice to login and logout, as would be the case with any other app. Instead of having an app that miraculously knows who the user is and doesn't provide a method to logout. – Ruard van Elburg Jul 23 '19 at 20:56
  • ID4 enables federated login. You login once at the ID4 server and connected sites pull the principal from there. No one said anything about not having a logout option, but that too happens at the ID4 server. – Chris Pratt Jul 23 '19 at 21:32
  • Well, idea was to have user info and logout button on public site which relies on same IDS4 as first app which is fully protected. Looks like Chris Pratt approach in my case doesn't work. User info and Logout button should be on each page (in header) and approach where I put ```Authorize``` attribute on controller and ```AllowAnonymous``` on action doesn't work. I still have ```User.Identity.IsAuthenticated=false```. – dewebeloper Jul 24 '19 at 06:46
  • @dewebeloper unless you share the auth cookie, you will have Authenticated Identity only after normal authentication (calling any protected action) on that app, not any other. But for your case more proper could be creating three apps (If you can't have everything in one). The first one -- a kind of menu and two others to be shown in Iframe under that menu. – d_f Jul 24 '19 at 10:25
0

Adding authorization and then turning it off with the AllowAnonymous attribute will not trigger authentication. The user has to be challenged at least once. Because only then a cookie will be created, and once created it is send along on each request, even when it is accessable anonymous.

In my case I have a public app where the login button does nothing more than challenge authentication, and return the user to the page it was on afterwards.

public class HomeController : Controller
{
    // available for any user
    public IActionResult Index()
    {
        // false for anonymous, true for authenticated users
        // also without the Authorize attribute.
        var isAuthenticated = User.Identity.IsAuthenticated;

        return View();
    }

    [Authorize]
    public IActionResult Login(string returnUrl)
    {
        return LocalRedirect(returnUrl);
    }
}

Like on the other site, add a login link to your menu that calls the login method. But in this case this is the only method that requires the user to login, assuming you don't have an Authorization filter or other Authorization attributes. If the user did login on IdentityServer then the cookie will be created automatically, unless prompt=login.

In Startup configure cookies, something like this:

services
    .AddAuthentication(options =>
    {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
    })
    .AddCookie("Cookies", options =>
    {
        options.Cookie.Name = ".MySite.Cookie";
    })
    .AddOpenIdConnect("oidc", "Open Id connect", options =>
    {
        options.SignInScheme = "Cookies";
        // etc

The user remains anonymous until the login link is clicked. If you send the user to this site then you can send it to the login link. Otherwise it's up to the user to login on your public mvc website.

Ruard van Elburg
  • 12,630
  • 2
  • 35
  • 52