質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
SAML

SAMLは、ユーザー認証に必要な情報をインターネットドメイン間で安全に交換することを目的としたXMLベースの標準規格。複数のWebサイト・サービスに一度ログインするだけで、SAML対応のクラウドサービスやWebアプリを利用することができます。

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Keycloak

Keycloakとは、一度の認証で多くのシステム利用が可能になるシングルサインオン(SSO)のオープンソースソフトウェアです。OpenID ConnectやSAMLなどのシングルサインオンのプロトコルに対応。IdPとして用いることができます。ソーシャルサービスでの認証機構の利用も可能です。

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

Q&A

解決済

1回答

330閲覧

CORSエラーの回避方法がわかりません

qafchel

総合スコア2

SAML

SAMLは、ユーザー認証に必要な情報をインターネットドメイン間で安全に交換することを目的としたXMLベースの標準規格。複数のWebサイト・サービスに一度ログインするだけで、SAML対応のクラウドサービスやWebアプリを利用することができます。

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Keycloak

Keycloakとは、一度の認証で多くのシステム利用が可能になるシングルサインオン(SSO)のオープンソースソフトウェアです。OpenID ConnectやSAMLなどのシングルサインオンのプロトコルに対応。IdPとして用いることができます。ソーシャルサービスでの認証機構の利用も可能です。

ASP.NET Web API

ASP.NET Web APIはブラウザやモバイル機器のようなクライアント向けのHTTPサービスを構築するフレームワークです。Microsoft .NET Frameworkがベースになっており、RESTfulサービスを構築するには理想的です。

0グッド

0クリップ

投稿2024/09/06 11:10

実現したいこと

開発環境においてCORSエラーを回避したい

発生している問題・分からないこと

Angular, ASP.NET Core Web API, Keycloakを用いたSAML2認証を組み合わせたアプリケーションにおいてCORSのエラーが発生しています。どうすれば回避できるのでしょうか?

エラーメッセージ中の以下のアドレスは次に対応します。
https://localhost:4200 : フロントエンド側(Angular)のアドレス
https://localhost:7055 : バックエンド側(ASP.NET Core Web API)のアドレス
https://localhost:8443 : Keycloakのアドレス

エラーメッセージ

error

1Access to XMLHttpRequest at 'https://localhost:8443/realms/(realm name)/protocol/saml?SAMLRequest=fJFNa8MwDIbvhf4H43tnx%2FloKpJAWBkUukuz7rCbk7ok4NiZ5ezj3y%2Ft2rHB6EUHSY%2F0vlKGstdigHL0rdmp11GhJx%2B9NgjflZyOzoCV2CEY2SsE30BVPm5B3HEYnPW2sZr%2BZm4jElE531lDyWad0%2B5QcyGSY5MeQnWMgiCp64Qn6TJK60REqyCg5Fk5nICcTvxEIY5qY9BL46cUF9GCrxY8eQo4xCEE4oWS9WSjM%2FK0Jqet9wMCY9o2UrcWPaRRFDKnpO6RVZ%2F4oO07u1phJw%2BUlFeZ99bg2CtXKffWNWq%2F2%2F43ccnjmFUn95dYNkiL%2BYyQ7HwTOKt2xS0yO6%2F%2BaZ3PLom%2F3ym%2BAAAA%2F%2F8DAA%3D%3D&RelayState=fHLe6EsBVGLe6Gh3cn9mzROQ' (redirected from 'https://localhost:7055/account/UserInfo') from origin 'https://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

該当のソースコード

Program.cs(前半部分)

1 2var builder = WebApplication.CreateBuilder(args); 3 4builder.Services.AddLogging(loggingBuilder => 5{ 6 loggingBuilder.AddConsole(); 7 loggingBuilder.AddDebug(); 8 loggingBuilder.SetMinimumLevel(LogLevel.Debug); 9}); 10 11#if DEBUG 12// CORSの有効化(開発時のみ) 13var MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; 14 15builder.Services.AddCors(options => 16{ 17 options.AddPolicy(name: MyAllowSpecificOrigins, 18 policy => 19 { 20 policy.WithOrigins("https://localhost:4200", "https://localhost:8443") 21 .AllowAnyHeader() 22 .AllowAnyMethod(); 23 }); 24}); 25#endif 26 27// Add services to the container. 28 29// 分散キャッシュの設定 30builder.Services.AddDistributedPostgreSqlCache(options => 31{ 32 options.ConnectionString = builder.Configuration.GetConnectionString("FlowDb"); 33 options.SchemaName = "public"; 34 options.TableName = "TestCache"; 35 options.DisableRemoveExpired = false; 36 options.ExpiredItemsDeletionInterval = TimeSpan.FromMinutes(30); 37}); 38 39builder.Services.AddAuthentication(options => 40{ 41 options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; 42 options.DefaultChallengeScheme = Saml2Defaults.Scheme; 43}) 44.AddCookie() 45.AddSaml2(options => 46{ 47 var entityId = builder.Configuration["Saml2:entityId"]; 48 var idpEntityId = builder.Configuration["Saml2:idpEntityId"]; 49 var metadataUrl = builder.Configuration["Saml2:IdpMetadataURL"]; 50 51 options.SPOptions.EntityId = new Sustainsys.Saml2.Metadata.EntityId(entityId); 52 options.SPOptions.AuthenticateRequestSigningBehavior = Sustainsys.Saml2.Configuration.SigningBehavior.Never; 53 options.SPOptions.PublicOrigin = new(entityId ?? String.Empty); 54 var idp = new Sustainsys.Saml2.IdentityProvider( 55 new Sustainsys.Saml2.Metadata.EntityId(idpEntityId), 56 options.SPOptions) 57 { 58 MetadataLocation = metadataUrl, 59 LoadMetadata = true, 60 }; 61 options.IdentityProviders.Add(idp); 62}); 63 64builder.Services.AddAuthorization(options => 65{ 66 options.AddPolicy("Saml2", policy => 67 { 68 policy.RequireClaim(ClaimTypes.NameIdentifier); 69 }); 70}); 71 72builder.Services.AddControllers(); 73builder.Services.AddSession(options => 74{ 75 options.IdleTimeout = TimeSpan.FromMinutes(30); 76 options.Cookie.HttpOnly = true; 77 options.Cookie.IsEssential = true; 78});

Program.cs

1 2var app = builder.Build(); 3 4// Configure the HTTP request pipeline. 5 6app.UseHttpsRedirection(); 7app.UseSession(); 8 9#if DEBUG 10// CORSの有効化(開発時のみ) 11app.UseCors(MyAllowSpecificOrigins); 12#endif 13 14app.UseAuthentication(); 15app.UseAuthorization(); 16 17app.MapControllers(); 18 19app.Run();

http.service.ts

1import { HttpClient, HttpHeaders } from '@angular/common/http'; 2import { Injectable } from '@angular/core'; 3import { Observable } from 'rxjs'; 4import { Endpoints } from '../constants/endpoints'; 5 6@Injectable({ 7 providedIn: 'root' 8}) 9export class HttpService { 10 11 constructor(private http: HttpClient) { } 12 13 get<T>(endpoint: string): Observable<T> { 14 const httpOptions = { 15 headers: new HttpHeaders({ 16 'Access-Control-Allow-Origin': '*', 17 }) 18 }; 19 20 return this.http.get<T>(Endpoints.getUrl(endpoint), httpOptions); 21 } 22 23 post<T>(endpoint: string, body: any | null): Observable<T> { 24 const httpOptions = { 25 headers: new HttpHeaders({ 26 'Access-Control-Allow-Origin': '*', 27 }) 28 }; 29 30 return this.http.post<T>(Endpoints.getUrl(endpoint), body, httpOptions); 31 } 32} 33

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

検索結果に従ってAngularからのHTTP GETのヘッダーに'Access-Control-Allow-Origin': '*'を追加したり、ASP.NET Core Web API側にAddCorsメソッドとUseCorsメソッドの呼び出しも追加しましたが解消できていません。

補足

バージョンは以下の通りです
.NET: 8
Angular: 18
Keycloak: 25

Keycloakでは、Valid redirect URIsに「https://localhost:7055/*」と「https://localhost:4200/*」を指定しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

qafchel

2024/09/09 02:08

いろいろ試しているところ、ログイン状態でないために自動的にKeycloakサーバーへのリダイレクトが発生しているときに「https://localhost:4200」から「https://localhost:8443」へのリダイレクトになっていて、そこでエラーが発生している感じのようです。
hqf00342

2024/09/09 04:52

エラーメッセージに書いてある通りですが、Access-Control-Allow-Originを付けるべきはkeycloakであってAngularでもASP.NETでもありません。(ASP.NETにはこのエラーとは別に必要です) OpenID connectならkeycloakの場合WebOriginsに設定すればつけられると思いますが SAMLで非同期通信はやったことが無いのでお役には立てそうにないです。
qafchel

2024/09/09 06:03

hqf00342さんご返答ありがとうございます。 おっしゃる通りAngular側からの呼び出しにおいてAccess-Control-Allow-Originを設定する必要がないことが分かったため、自己解決に記述したようにAngular側での処理からは除外するようにしました。 Keycloakでの設定では、バージョンが25だからなのかWeb Originsの設定項目を見つけることはできませんでした。その代わりにquarkus.propertiesに"https://ja.quarkus.io/guides/security-cors"に記述された設定項目に対する設定を追加することで行えそうという感じではありました。ただ、実際にはKeycloakへの暗黙的なリダイレクトを抑える方向で解決するようにしましたのでKeycloakへの設定は行いませんでした。
guest

回答1

0

自己解決

自己解決になりますが、以下の変更を行うことで回避することができました。

  1. Angular側において、以下の内容でsrc/proxy.conf.jsonを作成し、

    json

    1{ 2 "/api": { 3 "target": "https://localhost:7055", 4 "secure": false, 5 "pathRewrite": { 6 "^/api": "" 7 }, 8 "logLevel": "debug" 9 } 10}

    このファイルをangular.json$.projects.(Angularプロジェクト名).architect.serve.optionsの下に

    json

    1"serve": { 2 "proxyConfig": "src/proxy.conf.json" 3}

    と指定しました。

  2. Angular側からのASP.NET Web API側にあるAPIの呼び出しについて、ログイン処理のようにSAML2のIdpへのリダイレクトが行われる可能性があるものについてはHttpClient.get等ではなく、

    typescript

    1window.location.href = /api/account/login

    のようにwindow.location.hrefに設定する方式をとるように変更した。

  3. ASP.NET Web API側のコントローラーについて、暗黙的なSAML2のIdpへのリダイレクトが行われるのを避けるため、Authorize属性を付与しないように変更した。ログイン中かどうかの判定は各メソッドでUser.Identity.IsAuthenticatedの値をチェックするようにした。

また問題の解決とは別に、https://teratail.com/questions/256773等の記述から、クライアントからの呼び出しにおいてヘッダーへのAccess-Control-Allow-Originの付与にメリットはないとのことから、Angular側におけるhttp.service.tsから当該処理を削除しました。

投稿2024/09/09 04:56

qafchel

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問