user2243747
user2243747

Reputation: 2967

Identityserver3 - HybridFlow not returning profile scope

I have set-up identityserver3 and MVC4 client using this tutorial. When I configured client to use 'Implicit' flow things are working as expected and I am getting back 'profile' scope. i.e. I can find claims first_name and given_name. Below my configuration code.

Client and User configuration

public static class Users
{
    public static List<InMemoryUser> Get()
    {
        return new List<InMemoryUser>
        {
            new InMemoryUser
            {
                Username = "Bob",Password = "password",Subject = "1",
                Claims = new []
                {
                    new Claim(Constants.ClaimTypes.GivenName,"firstName"),
                    new Claim(Constants.ClaimTypes.FamilyName,"lastName")
                }
            }
        };
    }
}

public static class Clients
{
    public static IEnumerable<Client> Get()
    {
        return new[] 
        {
            new Client
            { 
                ClientId = "MVC",
                ClientName = "MVC Client Name",
                RedirectUris = new List<string>
                {
                    "https://localhost:44302/"
                },
                Flow = Flows.Implicit,
                AllowAccessToAllScopes = true
            }
        };
    }
}

Identity Server Configuration

public void Configuration(IAppBuilder app)
{
    JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

    app.Map("/identity", appBuilder => {
    appBuilder.UseIdentityServer(new IdentityServer3.Core.Configuration.IdentityServerOptions
    {
        SiteName = "Site Name",
        SigningCertificate = LoadCertificate(),
        RequireSsl = false,
        Factory = new IdentityServer3.Core.Configuration.IdentityServerServiceFactory()
            .UseInMemoryClients(Clients.Get())
            .UseInMemoryUsers(Users.Get())
            .UseInMemoryScopes(StandardScopes.All)
        });
    });

    app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions
    {
        AuthenticationType = "Cookies"
    });

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        Authority = "https://localhost:44302/identity",
        ClientId = "MVC",
        RedirectUri = "https://localhost:44302/",
        ResponseType = "id_token",                
        SignInAsAuthenticationType = "Cookies",
        Scope = "openid profile"
    });
}

In my MVC application I have secured Action on Home controller named 'Contact'

[Authorize]
public ActionResult Contact()
{            
    ClaimsPrincipal principal = User as ClaimsPrincipal;
    return View(principal.Claims);
}

And finally here is simple view

@model IEnumerable<System.Security.Claims.Claim>
@foreach (var item in Model)
{
    <div>
        <span>@item.Type</span>
        <span>@item.Value</span>
    </div>
}
</div>

Now when I run this app, after clicking on secure 'Contact' link I am being redirected to STS server and after providing credentials I can see below output.

Output

Note that claims given_name and family_name exists in the claims returned by STS.

Problem:

The moment I change Client to support Hybrid flow. I am not getting back claims given_name and family_name

I made below changes to my code.

Client configuration

 public static IEnumerable<Client> Get()
    {
        return new[] 
        {
            new Client
            { 
                ClientId = "MVC",
                ClientName = "MVC Client Name",
                RedirectUris = new List<string>
                {
                    "https://localhost:44302/"
                },
                Flow = Flows.Hybrid,//Changed this to Hybrid
                AllowAccessToAllScopes = true
            }
        };
    }

Server Configuration

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            Authority = "https://localhost:44302/identity",
            ClientId = "MVC",
            RedirectUri = "https://localhost:44302/",
            ResponseType = "code id_token token",  //Changed response type              
            SignInAsAuthenticationType = "Cookies",
            Scope = "openid profile"
        });

After running applicaton I can see below claims returned by STS

enter image description here

Note that claims given_name and family_name are missing this time.

Have I missed anything?

Upvotes: 4

Views: 787

Answers (1)

Brock Allen
Brock Allen

Reputation: 7435

When you only ask for an id_token all the claims for the user are in the id_token. When you change your request to get a token (either by asking for code or token) then only the user claims configured as "AlwaysInclude" are included in the id_token. The rest must be retrieved from the user info endpoint using the access_token you received. You can use the helper APIs in the IdentityModel library to easily access the user info endpoint. Our samples show how you can do this: https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/MVC%20OWIN%20Client%20(Hybrid)/Startup.cs#L66

Upvotes: 4

Related Questions