﻿namespace Nop.Plugin.Api.IdentityServer.Middlewares
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.Extensions.Primitives;

    public class IdentityServerScopeParameterMiddleware
    {
        private readonly RequestDelegate _next;

        public IdentityServerScopeParameterMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.Value.Equals("/connect/authorize", StringComparison.InvariantCultureIgnoreCase) ||
                context.Request.Path.Value.Equals("/oauth/authorize", StringComparison.InvariantCultureIgnoreCase))
            {
                if (!context.Request.Query.ContainsKey("scope"))
                {
                    var queryValues = new Dictionary<string, StringValues>();

                    foreach (var item in context.Request.Query)
                    {
                        queryValues.Add(item.Key, item.Value);
                    }

                    queryValues.Add("scope", "nop_api offline_access");

                    var newQueryCollection = new QueryCollection(queryValues);

                    context.Request.Query = newQueryCollection;
                }
            }

            await _next(context);
        }
    }
}
﻿namespace Nop.Plugin.Api.IdentityServer.Middlewares
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Internal;
    using Microsoft.Extensions.Primitives;

    public class IdentityServerScopeParameterMiddleware
    {
        private readonly RequestDelegate _next;

        public IdentityServerScopeParameterMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.Value.Equals("/connect/authorize", StringComparison.InvariantCultureIgnoreCase) ||
                context.Request.Path.Value.Equals("/oauth/authorize", StringComparison.InvariantCultureIgnoreCase))
            {
                // Make sure we have "nop_api" and "offline_access" scope

                var queryValues = new Dictionary<string, StringValues>();

                foreach (var item in context.Request.Query)
                {
                    if (item.Key == "scope")
                    {
                        string scopeValue = item.Value;

                        if (!scopeValue.Contains("nop_api offline_access"))
                        {
                            // add our scope instead since we don't support other scopes
                            queryValues.Add(item.Key, "nop_api offline_access");
                            continue;
                        }
                    }

                    queryValues.Add(item.Key, item.Value);
                }

                if (!queryValues.ContainsKey("scope"))
                {
                    // if no scope is specified we add it
                    queryValues.Add("scope", "nop_api offline_access");
                }

                var newQueryCollection = new QueryCollection(queryValues);

                context.Request.Query = newQueryCollection;

            }

            await _next(context);
        }
    }
}
Make sure we always add our nop_api scope in order for the token to have access to the resources. Also make sure we always add offline_access scope as it is required by the IdentityServer. This way even if empty scope is passed i.e if using Postman the scope is empty, we still can obtain tokens with the correct scope. This is done so that we don't force all clients to specify the scope if they don't know it.
Make sure we always add our nop_api scope in order for the token to have access to the resources. Also make sure we always add offline_access scope as it is required by the IdentityServer.
This way even if empty scope is passed i.e if using Postman the scope is empty, we still can obtain tokens with the correct scope. This is done so that we don't force all clients to specify the scope if they don't know it.
