thinktecture-ident-serverthinktecture

Unable to use IdentityManager API from Postman


I am using postman and I am trying to get the users list from identity Manager. But I am unable to configure the app correctly. I try to get the users from https://localhost/idm/api/users

I get the token with the API+idmgr+openid scopes and I have the Administrator role in my claims.

Here is the startup file:

namespace WebHost
{
    internal class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            LogProvider.SetCurrentLogProvider(new NLogLogProvider());

            string connectionString = ConfigurationManager.AppSettings["MembershipRebootConnection"];

            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

            app.UseOpenIdConnectAuthentication(new Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                Authority = "https://localhost/ids",
                ClientId = "postman",
                RedirectUri = "https://localhost",
                ResponseType = "id_token",
                UseTokenLifetime = false,
                Scope = "openid idmgr",
                SignInAsAuthenticationType = "Jwt",
                Notifications = new Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = n =>
                    {
                        n.AuthenticationTicket.Identity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        return Task.FromResult(0);
                    }
                }
            });

            X509Certificate2 cert = Certificate.Get();

            app.Map("/idm", adminApp =>
            {
                app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
                {
                    AllowedAudiences = new string[] { "https://localhost/ids" + "/resources" },
                    AuthenticationType = "Jwt",
                    IssuerSecurityTokenProviders = new[] {
                        new X509CertificateSecurityTokenProvider("https://localhost/ids", cert)
                    },
                    AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active
                });

                var factory = new IdentityManagerServiceFactory();
                factory.Configure(connectionString);

                var securityConfig = new ExternalBearerTokenConfiguration
                {
                    Audience = "https://localhost/ids" + "/resources",
                    BearerAuthenticationType = "Jwt",
                    Issuer = "https://localhost/ids",
                    SigningCert = cert,
                    Scope = "openid idmgr",
                    RequireSsl = true,
                };

                adminApp.UseIdentityManager(new IdentityManagerOptions()
                {
                    Factory = factory,
                    SecurityConfiguration = securityConfig
                });
            });

            app.Map(ConfigurationManager.AppSettings["IdentityServerSuffix"], core =>
            {
                IdentityServerServiceFactory idSvrFactory = Factory.Configure();
                idSvrFactory.ConfigureCustomUserService(connectionString);

                var options = new IdentityServerOptions
                {
                    SiteName = "Login",

                    SigningCertificate = Certificate.Get(),
                    Factory = idSvrFactory,
                    EnableWelcomePage = true,
                    RequireSsl = true
                };

                core.UseIdentityServer(options);
            });
        }
    }
}

What Am I missing?


Solution

  • For those who may want to know how I did it, well I made a lot of search about Owin stuff and how Identity Server works and find out my problem was not that far.

    I removed the JwtSecurityTokenHandler.InboundClaimTypeMap I removed the UseOpenId stuff (don't remove it if you are using an openId external login provider (if you are using google, facebook or twitter, there is classes for that, just install the nuget, it's pretty straight forward)

    This section let you configure the bearer token which is the default type token i used in my app(I decided to use password authentication to simplify Postman request to do automatic testing but I still user Code authentication in my apps)

    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
                {
                    Authority = ConfigurationManager.AppSettings["AuthorityUrl"],
                    ValidationMode = ValidationMode.ValidationEndpoint,
                    RequiredScopes = new[] { ConfigurationManager.AppSettings["ApiScope"] }
                });
    

    I have disabled the IdentityManagerUi interface as I was planning to use the API

     app.Map(ConfigurationManager.AppSettings["IdentityManagerSuffix"].ToString(), idmm =>
                {
                    var factory = new IdentityManagerServiceFactory();
                    factory.Configure(connectionString);
    
                    idmm.UseIdentityManager(new IdentityManagerOptions()
                    {
                        DisableUserInterface = true,
                        Factory = factory,
                        SecurityConfiguration = new HostSecurityConfiguration()
                        {
                            HostAuthenticationType = Constants.BearerAuthenticationType
                        }
                    });
                });
    

    And I configure the Identity Server like this:

    app.Map(ConfigurationManager.AppSettings["IdentityServerSuffix"], core =>
                {
                    IdentityServerServiceFactory idSvrFactory = Factory.Configure();
                    idSvrFactory.ConfigureCustomUserService(connectionString);
    
                    var options = new IdentityServerOptions
                    {
                        SiteName = ConfigurationManager.AppSettings["SiteName"],
    
                        SigningCertificate = Certificate.Get(),
                        Factory = idSvrFactory,
                        EnableWelcomePage = true,
                        RequireSsl = true,
                    };
    
                    core.UseIdentityServer(options);
                });
    

    In IdentityServerServiceFactory I call this chunk of code:

    var clientStore = new InMemoryClientStore(Clients.Get());
    

    And the code for the Client should be something like:

    public static Client Get()
            {
                return new Client
                {
                    ClientName = "PostMan Application",
                    ClientId = "postman",
                    ClientSecrets = new List<Secret> {
                            new Secret("ClientSecret".Sha256())
                        },
                    Claims = new List<Claim>
                        {
                            new Claim("name", "Identity Manager API"),
                            new Claim("role", IdentityManager.Constants.AdminRoleName),
                        },
                    **Flow = Flows.ResourceOwner**, //Password authentication
                    PrefixClientClaims = false,
                    AccessTokenType = AccessTokenType.Jwt,
                    ClientUri = "https://www.getpostman.com/",
                    RedirectUris = new List<string>
                        {
                            "https://www.getpostman.com/oauth2/callback",
                            //aproulx - 2015-11-24 -ADDED This line, url has changed on the postman side
                            "https://app.getpostman.com/oauth2/callback"
                        },
    
                    //IdentityProviderRestrictions = new List<string>(){Constants.PrimaryAuthenticationType},
                    AllowedScopes = new List<string>()
                        {
                            "postman",
                            "IdentityManager",
                            ConfigurationManager.AppSettings["ApiScope"],
                            Constants.StandardScopes.OpenId,
                            IdentityManager.Constants.IdMgrScope,
                        }
                };
            }
    

    On the postman side just do:

    POST /ids/connect/token HTTP/1.1
    Host: local-login.net
    Cache-Control: no-cache
    Postman-Token: 33e98423-701f-c615-8b7a-66814968ba1a
    Content-Type: application/x-www-form-urlencoded
    
    client_id=postman&client_secret=SecretPassword&grant_type=password&scope=APISTUFF&username=apiViewer&password=ICanUseTheApi
    

    Hope that it will help somebody