Sim*_*aur 8 c# oauth-2.0 swagger .net-core swashbuckle.aspnetcore
我想在我的 Web 应用程序中实现 OAuth,为此我在我的应用程序中添加了以下代码startup.cs
public static IServiceCollection AddSwaggerDocumentation(this IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "CombiTime API v1.0", Version = "v1" });
c.AddSecurityDefinition("OAuth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("http://localhost:4200/login"),
TokenUrl = new Uri("http://localhost:4200/connect/token")
}
}
});
c.OperationFilter<AuthorizeOperationFilter>();
c.AddSecurityRequirement(new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme{
Reference = new OpenApiReference{
Id = "Bearer", //The name of the previously defined security scheme.
Type = ReferenceType.SecurityScheme
}
},new List<string>()
}
});
});
return services;
}
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Versioned API v1.0");
c.DocumentTitle = "Title Documentation";
c.DocExpansion(DocExpansion.None);
c.RoutePrefix = string.Empty;
c.OAuthClientId("combitimeapi_swagger");
c.OAuthAppName("Combitime API");
c.OAuthUsePkce();
});
return app;
}
Run Code Online (Sandbox Code Playgroud)
代码AuthorizeOperationFilter如下:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
// Since all the operations in our api are protected, we need not
// check separately if the operation has Authorize attribute
operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
operation.Security = new List<OpenApiSecurityRequirement>
{
new OpenApiSecurityRequirement
{
[
new OpenApiSecurityScheme
{
Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "oauth2"}
}
] = new[] {"combitimeapi"}
}
};
}
Run Code Online (Sandbox Code Playgroud)
通过使用此代码,我在我的 swagger UI 上获得一个“授权”按钮,当我单击该按钮时,我将重定向到我的登录页面(基于角度的前端)。所以我给出了我的AuthorizationUrlashttp://localhost:4200/login然后当我重定向到登录页面时,我使用有效的凭据登录,我使用 jwt 令牌进行登录,为此我在我的中添加了以下代码startup.cs
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
Run Code Online (Sandbox Code Playgroud)
我想在使用有效凭据登录后重定向回 swagger UI,但问题是登录后我被重定向到仪表板。请帮助我或让我知道我做错了什么。
我从 swagger 重定向到登录页面后形成的网址是:
http://localhost:4200/login?response_type=code&client_id=combitimeapi_swagger&redirect_uri=http:%2F%2Flocalhost:61574%2Foauth2-redirect.html&state=V2VkIEZlYiAxNyAyMDIxIDIyOjU3OjQ2IEdNVCswNTMwIChJbmRpYSBTdGFuZGFyZCBUaW1lKQ%3D%3D&code_challenge=mT0amBTJgczCZmNSZAYVfjzzpaTiGb68XlyR3RNHuas&code_challenge_method=S256
Run Code Online (Sandbox Code Playgroud)
我的前端在端口 4200 上运行。我的 swagger 在端口 61574 上运行。但是在输入有效凭据后我没有被重定向到 swagger UI 请帮助我。
首先,让我为您的图片添加一些细节:
因此,对于 API 应用程序,我们必须添加一个具有配置我们的 swagger 的辅助方法的类:
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddSwaggerDocumentation(this IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "CombiTime API v1.0", Version = "v1" });
c.AddSecurityDefinition(
"oauth2",
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("https://lvh.me:4201/connect/authorize"),
TokenUrl = new Uri("https://lvh.me:4201/connect/token"),
Scopes = new Dictionary<string, string> {
{ "combitimeapi", "Demo API" }
}
}
}
});
c.OperationFilter<AuthorizeOperationFilter>();
c.AddSecurityRequirement(
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme{
Reference = new OpenApiReference{
Id = "oauth2", //The name of the previously defined security scheme.
Type = ReferenceType.SecurityScheme
}
},
new List<string>()
}
});
});
return services;
}
public static IApplicationBuilder UseSwaggerDocumentation(this IApplicationBuilder app)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Versioned API v1.0");
c.DocumentTitle = "Title Documentation";
c.DocExpansion(DocExpansion.None);
c.RoutePrefix = string.Empty;
c.OAuthClientId("combitimeapi_swagger");
c.OAuthAppName("Combitime API");
c.OAuthScopeSeparator(",");
c.OAuthUsePkce();
});
return app;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意财产AuthorizationUrl和财产TokenUrl。该AuthorizationUrl属性应指向我们的 OAuth2 服务器授权端点。请记住,授权端点和登录页面是不同的端点。https://lvh.me:4201/.well-known/openid-configuration如果我们的应用程序使用 ASP.NET Core 和 IdentityServer,我们可以通过访问 url 来获取前端应用程序的所有已知端点。
接下来,Startup.cs我们的 API 应用程序应包含:
public void ConfigureServices(IServiceCollection services)
{
// ... some your code ...
services.AddSwaggerDocumentation();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication("Bearer", options =>
{
options.ApiName = "combitimeapi";
options.Authority = "https://lvh.me:4201";
});
// ... some your code ...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... some your code ...
app.UseSwaggerDocumentation();
app.UseRouting();
app.UseAuthorization();
// ... some your code ...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Run Code Online (Sandbox Code Playgroud)
请不要忘记[Authorize]向所有控制器添加属性,因为您AuthorizeOperationFilter认为已经完成了。
让我们寻找前端和授权部分所需的更改。您应该配置一些特定的内容,例如:
该类Startup.cs应包含:
public void ConfigureServices(IServiceCollection services)
{
// ... some your code ...
services.AddCors(policies => {
policies.AddDefaultPolicy(builder => {
builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin();
});
});
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => {
options.Clients.AddIdentityServerSPA("forntend", cfg => {});
options.Clients.AddNativeApp("combitimeapi_swagger", cfg => {
cfg
.WithRedirectUri("https://lvh.me:5001/oauth2-redirect.html")
.WithScopes("combitimeapi");
});
options.ApiResources.AddApiResource("combitimeapi", cfg => {
cfg.WithScopes("combitimeapi");
});
})
.AddApiResources();
services
.AddAuthentication(
x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddIdentityServerJwt();
// ... some your code ...
}
Run Code Online (Sandbox Code Playgroud)
我使用这里.AddIdentityServerJwt()而不是你的,.AddJwtBearer(...)因为我没有你的钥匙和其他特定选项。
前端应用程序配置为使用端口 4201(用于 HTTPS)和 4200(用于 HTTP),API 应用程序配置为使用端口 5001(用于 HTTPS)和 5000(用于 HTTP)。
现在您可以运行这两个应用程序并转到该页面https://lvh.me:5001/index.html并按“授权”按钮以获取如下对话框:
输入您的密码,标记范围并按“授权”,在您验证自己身份后,您将获得:
如果您没有获得成功的结果,请检查前端应用程序的日志,通常它包含错误,可以帮助您找出问题。
希望以上文字对您有所帮助。
如果您查看 OAuth 网站,该案例被描述为“按请求定制”
\n\n\n按请求定制
\n通常,开发人员会认为他们需要能够在每个授权请求上使用不同的重定向 URL,并尝试更改每个请求的查询字符串参数。这不是重定向 URL 的预期用途,授权服务器不应允许这样做。服务器应拒绝任何带有与注册 URL 不完全匹配的重定向 URL 的授权请求。
\n
\n\n如果客户端希望在重定向 URL 中包含特定于请求的数据,则可以使用 \xe2\x80\x9cstate\xe2\x80\x9d 参数来存储用户重定向后将包含的数据。它可以对状态参数本身中的数据进行编码,也可以使用状态参数作为会话 ID 将状态存储在服务器上。
\n
我希望这对您的探索有所帮助。
\n来源:https ://www.oauth.com/oauth2-servers/redirect-uris/redirect-uri-registration/
\n