3

I am trying to authorize the swagger api with the okta configuration using ASP.NET core 2.2.

Followed the instruction from this link https://app.swaggerhub.com/help/enterprise/user-management/sso/okta

But quite not sure how can I do it.

Okta link

https://developer.okta.com/quickstart/?_ga=2.180885607.1554519477.1569975022-1481902663.1569975022#/angular/dotnet/aspnetcore

here is my Asp.net code

ConfigureSwagger(services);

protected virtual void ConfigureSwagger(IServiceCollection services)
        {
            // to view online help, goto ~/swagger/
            services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();

            services.AddSwaggerGen(options =>
            {
                // add a custom operation filter which sets default values
                options.OperationFilter<SwaggerDefaultValues>();
            });
            services.ConfigureSwaggerGen(options => { });
        }


 public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
    {
        readonly IApiVersionDescriptionProvider provider;

        /// <summary>
        /// Initializes a new instance of the <see cref="ConfigureSwaggerOptions"/> class.
        /// </summary>
        /// <param name="provider">The <see cref="IApiVersionDescriptionProvider">provider</see> used to generate Swagger documents.</param>
        public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => this.provider = provider;

        /// <inheritdoc />
        public void Configure(SwaggerGenOptions options)
        {
            // add a swagger document for each discovered API version
            // note: you might choose to skip or document deprecated API versions differently
            foreach (var description in provider.ApiVersionDescriptions)
            {
                options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
            }

            options.OrderActionsBy(apiDesc => apiDesc.RelativePath);

            options.IncludeXmlComments(Path.ChangeExtension(typeof(Startup).GetTypeInfo().Assembly.Location, "xml"));
            options.DescribeAllEnumsAsStrings();
            options.DescribeStringEnumsInCamelCase();

            //options.AddSecurityDefinition("oauth2",
            //    new OAuth2Scheme
            //    {
            //        Type = "oauth2",
            //        Flow = "implicit",
            //        AuthorizationUrl = new Uri("/connect/authorize", UriKind.Relative).ToString(),
            //        Scopes = new Dictionary<string, string>
            //        {
            //            {"api1", "DEMO API"}
            //        }
            //    });

            //options.AddSecurityRequirement(new[] { "oauth2", "api1" });

            options.AddSecurityDefinition("oauth2",
                new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.OAuth2,

                    Flows = new OpenApiOAuthFlows
                    {
                        Implicit = new OpenApiOAuthFlow
                        {
                            AuthorizationUrl = new Uri("/connect/authorize", UriKind.Relative),
                            Scopes = new Dictionary<string, string>
                            {
                                {Program.ResourceIdentifier, Program.ApplicationName}
                            }
                        }
                    }
                });

            options.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "oauth2"
                        }
                    },
                    new[] {"oauth2", Program.ResourceIdentifier }
                }
            });

            options.EnableAnnotations();

            //options.DocInclusionPredicate((docName, apiDesc) =>
            //{
            //    if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false;

            //    var versions = methodInfo.DeclaringType
            //        .GetCustomAttributes(true)
            //        .OfType<ApiVersionAttribute>()
            //        .SelectMany(attr => attr.Versions);

            //    return versions.Any(v => $"v{v.ToString()}" == docName);
            //});
        }

        static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
        {
            var info = new OpenApiInfo
            {
                Title = Program.ApplicationName,
                Version = $"v{description.ApiVersion}",
                Description = "A sample application with Swagger, Swashbuckle, and API versioning."

            };

            if (description.IsDeprecated)
            {
                info.Description += " This API version has been deprecated.";
            }

            return info;
        }
    }


public static void UseSwaggerMiddleware(this IApplicationBuilder app, IApiVersionDescriptionProvider provider)
        {
            app.UseSwagger();
            // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                // build a swagger endpoint for each discovered API version
                foreach (var description in provider.ApiVersionDescriptions)
                {
                    c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
                }

                //OAuth2
                c.OAuthClientId("{clientId}");
                //c.OAuth2RedirectUrl("");
                //c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
                c.OAuthClientSecret("{ClientSecret}");
                c.OAuthAppName("{AppName}");
                c.OAuthScopeSeparator("openid profile email");
                c.OAuthAdditionalQueryStringParams(new Dictionary<string, string>
                {
                    { "response_type","token"}
                });

            });
        }

enter image description here

Errors Hide

Auth error
{"state":"VGh1IE9jdCAwMyAyMDE5IDE1OjI4OjEyIEdNVCsxMDAwIChBVVMgRWFzdGVybiBTdGFuZGFyZCBUaW1lKQ==","error":"unsupported_response_type","error_description":"The+response+type+is+not+supported+by+the+authorization+server.+Configured+response+types:+[id_token,+code]."}

How do I configure with swagger authorization client with JWT token.

San Jaisy
  • 15,327
  • 34
  • 171
  • 290
  • So are you running an identity provider of your own at /connect/authorize? Otherwise that needs to be the Okta authorization URL. – juunas Oct 02 '19 at 07:29
  • @juunas I think you are correct, but where do I find authorization URL for okta. – San Jaisy Oct 02 '19 at 07:37
  • Seems like it looks like this: https://{yourOktaDomain}/oauth2/v1/authorize – juunas Oct 02 '19 at 07:38
  • @juunas - do I need to add all the swagger url in the okta configuration ? – San Jaisy Oct 02 '19 at 07:43
  • Yeah it will need to allow a swagger URL as a redirect URI – juunas Oct 02 '19 at 07:44
  • how do I use https://{yourOktaDomain}/oauth2/v1/authorize on AuthorizationUrl = new Uri("/connect/authorize", UriKind.Relative) since it is URI and I am using the localhost for development – San Jaisy Oct 02 '19 at 07:46
  • `new Uri("https://{yourOktaDomain}/oauth2/v1/authorize")` – juunas Oct 02 '19 at 07:47
  • This gives me an error – San Jaisy Oct 02 '19 at 07:47
  • What error? And of course, did you replace {yourOktaDomain} with your actual domain? – juunas Oct 02 '19 at 07:48
  • A relative URI cannot be created because the 'uriString' parameter represents an absolute URI. AuthorizationUrl = new Uri("https://dev-166545.okta.com/oauth2/v1/authorize", UriKind.Relative), – San Jaisy Oct 02 '19 at 07:49
  • Take away the UriKind argument – juunas Oct 02 '19 at 07:50
  • @juunas How do I defined the scope ? keep getting the error as on the screen shot – San Jaisy Oct 03 '19 at 02:15
  • Seems like Okta doesn't support implicit grant for the app or it is not enabled – juunas Oct 03 '19 at 05:38
  • Check your request in web browser, what is the redirecr uri? – Edward Oct 03 '19 at 06:22
  • @TaoZhou I am still facing the old issue. – San Jaisy Oct 03 '19 at 06:29
  • If you make a test with [demo](https://github.com/okta/samples-aspnetcore/) and your okta configuration, can you successfully sign? – Edward Oct 03 '19 at 06:32
  • Yes I am able to successfully sign in. Its the issue with swagger setup and I am not aware what is causing the issue – San Jaisy Oct 03 '19 at 06:36
  • I got this log from OKTA OIDC authorization request failure : illegal_custom_scope what does this mean – San Jaisy Oct 03 '19 at 06:49
  • @juunas how do I support a custome scope because I have c.OAuthScopeSeparator("openid profile email id-gateway-api"). – San Jaisy Oct 03 '19 at 07:07
  • I think I have a issue with one custome scope {{id-gateway-api}} Can anyone tell me how can I register this scope in okta dev account. I didn't find any link – San Jaisy Oct 03 '19 at 07:18
  • For custom scope, you could follow [Create Scopes](https://developer.okta.com/docs/guides/customize-authz-server/create-scopes/) – Edward Oct 03 '19 at 08:08
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/200337/discussion-on-question-by-san-jaisy-swagger-authorization-with-okta-configuratio). – Samuel Liew Oct 03 '19 at 09:30
  • @TaoZhou I did that already and facing the same issues as you can check the new question https://stackoverflow.com/questions/58214596/auth-error-invalid-scope-error-descriptioncustomscopesarenotallowedfor – San Jaisy Oct 04 '19 at 00:31

1 Answers1

1

Finally found the solution

Need to do this configuration on asp.net core

public static void UseSwaggerMiddleware(this IApplicationBuilder app, IApiVersionDescriptionProvider provider, IConfiguration Configuration)
        {
            app.UseSwagger();
            // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                // build a swagger endpoint for each discovered API version
                foreach (var description in provider.ApiVersionDescriptions)
                {
                    c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
                }

                //c.SwaggerEndpoint("/swagger/v2/swagger.json", "DEMO Api v2");
                //c.SwaggerEndpoint("/swagger/v1/swagger.json", "DEMO Api v1");

                //OAuth2
                var OktaConfig = new OktaConfig();
                Configuration.GetSection("OktaConfig").Bind(OktaConfig);
                c.OAuthClientId(OktaConfig.ClientId);
                c.OAuth2RedirectUrl($"{OktaConfig.RedirectUrl}/swagger/oauth2-redirect.html");
                c.OAuthUseBasicAuthenticationWithAccessCodeGrant();
                c.OAuthClientSecret(OktaConfig.ClientSecret);
                c.OAuthAppName(OktaConfig.ClientName);
                c.OAuthScopeSeparator($"openid profile email {Program.ResourceIdentifier}");
                c.OAuthAdditionalQueryStringParams(new Dictionary<string, string>
                {
                    { "response_type","token"},
                    { "nonce", "nonce" }
                });
                //c.ConfigObject.DeepLinking = true;

            });
        }

And need to add policies and rule

added swagger

San Jaisy
  • 15,327
  • 34
  • 171
  • 290