【问题标题】:Angular 8 CRUD With OAuth2.0 In WebAPI fails with error: "unsupported_grant_type"在 Web API 中使用 OAuth 2.0 的 Angular 8 CRUD 失败并出现错误:“unsupported_grant_type”
【发布时间】:2019-12-02 15:36:49
【问题描述】:

我正在尝试使用 Angular 8 CRUD With OAuth2.0 In WebAPI (https://www.c-sharpcorner.com/article/angular-8-crud-with-oauth2-0-in-webapi-part-2/) 文章使用 WebApi 2 设置 OAuth 登录。

我已经剪切并粘贴了他的代码,但我得到了:

400(错误请求)错误:“unsupported_grant_type”

当我使用 http://localhost/oauth/token 回调我的 Visual Studio 2015 IIS express 实例时

我浏览了十几篇文章,都说要包含 application/x-www-urlencoded 的内容类型头,我已经完成了,但我仍然无法让这个该死的东西工作!

他有他的用户认证是一个服务,看起来像这样:

import {HttpClient,HttpHeaders} from '@angular/common/http';    
import { ProductDTO } from '../app/ProductDTO';    
import { Observable } from 'rxjs';    
@Injectable({    
  providedIn: 'root'    
})    
export class ProductService {    
  ApiUrl='http://localhost:57046/';    
  constructor(private httpclient: HttpClient) { }    

  UserAuthentication(UserName: string,Password: string):Observable<any>{    
   let credentials='username=' +UserName  + '&password=' +Password +'&grant_type=password';     
   var reqHeader = new HttpHeaders({'Content-Type': 'application/x-www-urlencoded','No-Auth':'True' });    
  return this.httpclient.post<any>(this.ApiUrl+'token',encodeURI(credentials),{headers:reqHeader});    
  }    
}

正在接收 OAuth 请求的后端是:

public class UtiliAuthProvider : OAuthAuthorizationServerProvider
    {
        private const string IPW = "invalid_password";
        private const string IPWC = "invalid_password_recaptcha";

        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;
            string jwtName = context.Parameters.Get(ConfigurationManager.AppSettings["WebJWTName"]);

            if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
            {
                context.TryGetFormCredentials(out clientId, out clientSecret);
            }

            if (context.ClientId == null || jwtName.Equals(ConfigurationManager.AppSettings["WebJWTProg"]))
            {
                context.Validated(ConfigurationManager.AppSettings["AudienceId"]);
            }
            else
            {

                if (context.ClientId == null)
                {
                    context.SetError("invalid_clientId", "client_Id is not set");
                }
                else
                {

                    if (AudienceProvider.FindAudience(context.ClientId) == null)
                    {
                        context.SetError("invalid_clientId", $"Invalid client_id '{context.ClientId}'");
                    }
                    else
                    {
                        context.Validated();
                    }
                }
            }

            return Task.FromResult<object>(null);
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { ConfigurationManager.AppSettings["CORSUrl"] });

            ApplicationUserManager userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
            UtiliUserModel user = await userManager.FindAsync(context.UserName, context.Password);

            if (user == null)
            {
                UtiliUserModel failUser = await userManager.FindByNameAsync(context.UserName);

                if (failUser == null)
                {
                    context.SetError("user_not_found", "Please check your user name and try again.");
                    return;
                }

                await userManager.AccessFailedAsync(failUser.Id);

                if (await userManager.IsLockedOutAsync(failUser.Id))
                {
                    ContextSetErrorLockOut(context);
                    return;
                }

                int attemptsLeft = userManager.MaxFailedAccessAttemptsBeforeLockout - failUser.AccessFailedCount;

                context.SetError(attemptsLeft == 1 ? IPWC : IPW, $"Incorrect password. You have {attemptsLeft} attempt{(attemptsLeft > 1 ? "s" : "")} left before account is locked out.");
                return;
            }

            if (await userManager.IsLockedOutAsync(user.Id))
            {
                ContextSetErrorLockOut(context);
                return;
            }

            if (user.AccessFailedCount > 0) await userManager.ResetAccessFailedCountAsync(user.Id);

            IFormCollection formData = await context.Request.ReadFormAsync();
            ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");
            oAuthIdentity.AddClaim(new Claim(ConfigurationManager.AppSettings["WebJWTName"], formData[ConfigurationManager.AppSettings["WebJWTName"]]));
            oAuthIdentity.AddClaim(new Claim(ConfigurationManager.AppSettings["ScopeClaim"], new UtiliportalViews(null).IsCurrentRoleAnyAdmin(context.UserName) ? ConfigurationManager.AppSettings["ScopeClaimAdmin"] : ConfigurationManager.AppSettings["ScopeClaimUser"]));
            context.Validated(new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties(new Dictionary<string, string> {{ UtiliportalDbConstants.AudiencePropertyKey, context.ClientId ?? string.Empty }})));
        }

        private static void ContextSetErrorLockOut(OAuthGrantResourceOwnerCredentialsContext context)
        {
            context.SetError("locked_out", "This account has been locked.");
        }
    }

这个后端已经工作了很多年,与当前的 AngularJS 客户端没有任何问题。现在尝试将网站重写为 Angular 8,导致这种废话。

有人可以发布一个工作示例,说明如何使用 Visual Studio IIS Express 服务器调用 OAuth/WebApi 2.0 登录令牌。

【问题讨论】:

    标签: angular asp.net-web-api oauth iis-express webapi


    【解决方案1】:

    以下代码使用 OpenIddict 库将带有客户端 ID 和机密的 oAuth 2 密码授权类型发送到配置了 JWT 令牌生成的 dotnet core 3 服务器。

    在 Angular 的身份验证服务中试试这个:

    export interface JWT {
        token_type: string;
        access_token: string;
        expires_in: number;
    }
    
    @Injectable()
    export class AuthService {
    
        private api = `${environment.serverURL}/connect/token`;
        private clientID = `${environment.clientID}`;
        private secret = `${environment.secret}`;
        private currentTokenSubject: BehaviorSubject<JWT>;
    
        constructor(private http: HttpClient){}
    
        login(email: string, password: string): any {
            const payload = new HttpParams()
                .append('grant_type', 'password')
                .append('redirect_uri', 'http://localhost:4200')
                .append('client_id', this.clientID)
                .append('client_secret', this.secret)
                .append('scope', 'email profile roles')
                .append('username', email)
                .append('password', password);
             return this.http.post<JWT>(this.api, payload).pipe(map(token => {
                 localStorage.setItem('token', JSON.stringify(token));
                 this.currentTokenSubject.next(token);
             }));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 2022-03-03
      • 2020-01-28
      • 2022-07-03
      • 2018-02-11
      • 2019-04-22
      相关资源
      最近更新 更多