0

セキュリティで保護されたIdentity Server 4で動作するWeb APIアプリケーションで作業しています。ユーザーは、JavaScriptクライアントを使用して暗黙フローを使用して認証されます。HttpContextからIdentityResourceスコープのjsonデータを読み取る方法

Web APIクライアントでIdentityResourceスコープを読み取る際に問題が発生しています。 Startup.csでapp.UseIdentityServerAuthentication()を呼び出すと、設定に何か不足している可能性があります。 User.Claimsコレクションを調べると、これらのIdentityResourceスコープのいずれのJSONデータも表示されません。

JavaScriptクライアントでは、oidc-client.jsライブラリを使用してスコープデータを表示できます。しかし、Web APIアプリケーションでスコープデータを読み取ることはできません。 JavaScriptクライアントで

、私は活字体でこれを行うことにより、JSONブロブとして格納された範囲のデータを見ることができます:私のウェブAPIプロジェクトで

class MyService { 
    private _userManager: Oidc.UserManager; 

    private _createUserManager(authority: string, origin: string) { 

    // https://github.com/IdentityModel/oidc-client-js/wiki#configuration 
    var config : Oidc.UserManagerSettings = { 
     authority: authority, 
     client_id: "myapi", 
     redirect_uri: `${origin}/callback.html`, 
     response_type: "id_token token", 
     scope: "openid profile user.profile user.organization ...", 
     post_logout_redirect_uri: `${origin}/index.html` 

    }; 

    this._userManager = new Oidc.UserManager(config); 
    } 

    // snip 
    user() { 
    this._userManager.getUser().then(user => { 

      const userProfile = JSON.parse(user.profile["user.profile"]); 
      console.log(userProfile); 

      const userOrganization = JSON.parse(user.profile["user.organization"]); 
      console.log(userOrganization); 

     }); 

    } 
} 

、私が持っている:

public class Startup 
{ 
    public IConfigurationRoot Configuration { get; set; } 
    public IContainer Container { get; set; } 

    public Startup(IHostingEnvironment env) 
    { 
     var configurationBuilder = new ConfigurationBuilder(); 

     if (env.IsDevelopment()) 
     { 
      configurationBuilder 
       .SetBasePath(env.ContentRootPath) 
       .AddJsonFile("appsettings.json"); 

      env.ConfigureNLog("nlog.development.config"); 
     } 
     else 
     { 
      configurationBuilder.AddEnvironmentVariables(); 

      env.ConfigureNLog("nlog.config"); 
     } 

     Configuration = configurationBuilder.Build(); 
    } 

    public IServiceProvider ConfigureServices(IServiceCollection services) 
    { 
     services 
      .AddMvcCore() 
      .AddJsonFormatters() 
      .AddAuthorization(); 

     services.AddCors(); 

     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
     services.AddScoped<IRestService, RestService>(); 

     var builder = AutoFacConfig.Create(Configuration); 
     builder.Populate(services); 

     Container = builder.Build(); 

     return new AutofacServiceProvider(Container); 
    } 

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     app.UseCors(policy => 
     { 
      policy 
       .WithOrigins(
        "http://app.local:5000" 
       ) 
       .AllowAnyHeader() 
       .AllowAnyMethod() 
       .AllowCredentials(); 
     }); 

     ConfigureExceptionHandling(app, env); 
     ConfigureOidc(app); 

     app.UseMvc(); 

    } 

    private void ConfigureExceptionHandling(IApplicationBuilder app, IHostingEnvironment env) 
    { 
     if (env.IsDevelopment()) 
     { 
      app.UseDeveloperExceptionPage(); 
     } 
    } 

    private void ConfigureOidc(IApplicationBuilder app) 
    { 

     app.UseCors("default"); 

     app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions 
     { 
      Authority = Configuration["IdentityServerUrl"], 
      AllowedScopes = { "api1", "openid", "profile", "user.profile", "user.organization" ... }, 
      ApiName = "myapi", 

      RequireHttpsMetadata = false 
     }); 
    } 
} 

問題私がスコープを読むためにクレームにアクセスしようとするときです。ユーザーが認証されると、要求のヘッダーにあるトークンをWeb APIエンドポイントに渡します。私はスコープを読んでみたいが、できないBaseControllerを持っている。

public class BaseController : Controller 
{ 
    private ApplicationUser _user; 

    public string UserId => CurrentUser?.UserInfo.Id; 

    public string OrganizationId => CurrentUser?.Organization.Id; 

    [CanBeNull] 
    public ApplicationUser CurrentUser 
    { 
     get 
     {   
      var claims = Request.HttpContext.User.Claims.ToList(); 

      _user = new ApplicationUser 
      { 
       UserInfo = claims.Where(f => f.Type == "user.profile").Select(s => s.Value).FirstOrDefault(), 
       OrganizationInfo = claims.Where(f => f.Type == "user.organization").Select(s => s.Value).FirstOrDefault() 
      }; 

      return _user; 
     } 
    } 
} 

あれば、私はクレームコレクションを見て、私はタイプと値については、以下を参照してください。

NBF:1499441027

EXP:1499444627の

ISS:https://identity-service ....

aud:https://identity-service..../resources

AUD:myapi

CLIENT_ID:myapi

サブ:the_user

AUTH_TIME:1499441027

IDP:ローカル

範囲:OpenIDを

範囲:

範囲をプロファイリング:user.profile

範囲:user.organization

...

範囲:myapi

AMR:PWD

私はC#のからのスコープデータを読み込むにはどうすればよいですか?

ユーザの方。組織スコープが、私のようなデータ構造を読み取るために期待してい:

{ 
    "Id":"some id", 
    "BusinessCategory":"some category", 
    "Name":"some name" 
} 

答えて

0

範囲を、それがそのようである理由です、タイプで、プロファイルはスコープのいずれかの値です。あなたはどのような価値観を見たいですか?値そのものなので、値はありません。あなたはそれを求めている: AllowedScopes = { "API1"、 "OpenIDの"、 "プロファイル"、 "user.profile"、...}、

、それはあなたがあなたの範囲になっているものですクレームリスト

あなたが主張リストから特定の値を取得したい場合は、あなたも、これは誰にも便利です場合

User.FindFirst(JwtRegisteredClaimNames.Email).Valueの

+0

、user.organizationと呼ばれる範囲のために、私はそれはのようなデータが含まれていることを期待します: "some id"、 "BusinessCategory": "いくつかのカテゴリ"、 "名前": "some name" このjson blobは、クレームコレクションからフェッチしたいものです。 スコープタイプをフィルタリングすると、プロファイル値のスコープ名のみが表示されます。私はjavascriptクライアントでこのデータを参照してください。 –

0

を使用してJwtRegisteredClaimNamesを使用することができます。私はハックを実装しました。ミドルウェアにIDサーバーのユーザー情報エンドポイントを呼び出すためのコードを追加しました。ユーザー情報エンドポイントは、必要なデータを返します。私はこのデータを使って手動でクレームを追加します。

私は私のConfigureメソッドにこのコードを追加しました: { 「ID」:異なるスコープを使用するには

app.Use(async (context, next) => 
{ 

    if (context.User.Identity.IsAuthenticated) 
    { 
     using (var scope = Container.BeginLifetimeScope()) 
     { 
      // fetch resource identity scopes from userinfo endpoint 
      var restService = scope.Resolve<IRestService>(); 
      var token = context.Request.Headers["Authorization"] 
       .ToString().Replace("Bearer ", string.Empty); 

      restService.SetAuthorizationHeader("Bearer", token); 

      // fetch data from my custom RestService class and 
      // serialize into my custom ScopeData object 
      var data = await restService.Get<ScopeData>(
       Configuration["IdentityServerUrl"], "connect/userinfo"); 

      if (data.IsSuccessStatusCode) 
      { 

       // add identity resource scopes to claims 
       var claims = new List<Claim> 
       { 
        new Claim("user.organization", data.Result.Organization), 
        new Claim("user.profile", data.Result.UserInfo) 
       }; 

      } 
      else 
      { 
       sLogger.Warn("Failed to retrieve identity scopes from profile service."); 
       context.Response.StatusCode = (int) HttpStatusCode.InternalServerError; 
      } 
     } 


    } 

    await next(); 
}); 
関連する問題