6

Tôi đang cố gắng tạo một trang web AngularJs gửi thông tin đăng nhập và mật khẩu tới một ASP.NET WebApi phụ trợ và đăng nhập người dùng này bằng Thinktecture.AngularJs ASP.NET WebApi xác thực với Thinktecture

Tôi có Thinktecture làm việc tốt với dự án khác, ASP.NET MVC, sử dụng Liên kết WS. Bây giờ tôi đang cố gắng làm một cái gì đó tương tự nhưng thay đổi một số thành phần và tôi không thể làm cho nó hoạt động.

Làm cách nào để gửi từ ASP.NET WebApi tên người dùng và mật khẩu đến Thinktecture và làm cho nó được xác thực?

using System.Collections.Generic; 
using System.IdentityModel.Services; 
using System.Web.Http; 
using WebApi_AngularJs.Model; 

namespace WebApi_AngularJs.Controllers 
{ 
    public class AuthorizationController : ApiController 
    {  
     // POST: api/Authorization 
     public LoginResponse Post([FromBody]Login data) 
     { 
      //HOW TO SEND data.user and data.password to ThinkTecture and get 
      //response if user valid or not?? 
      var response = new LoginResponse { access_token = "token", data = "data"}; 
      return response; 
     } 

    } 
} 

Cảm ơn bạn!

Trả lời

5

Cuối cùng, sau khi đọc rất nhiều tôi có điều này:

Trong AngularJS:

'use strict'; 
app.factory('authService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) { 

var serviceBase = 'http://localhost:64346/'; 
var authServiceFactory = {}; 

var _authData = localStorageService.get('authorizationData'); 

var _authentication = { 
    isAuth: _authData != null? true : false, 
    userName: _authData != null ? _authData.userName : "" 
}; 

var _saveRegistration = function (registration) { 

    _logOut(); 

    return $http.post(serviceBase + 'api/account/register', registration).then(function (response) { 
     return response; 
    }); 

}; 

var _login = function (loginData) { 

    var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password; 

    var deferred = $q.defer(); 

    $http.post(serviceBase + 'api/authorization', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) { 

     localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName }); 

     _authentication.isAuth = true; 
     _authentication.userName = loginData.userName; 

     deferred.resolve(response); 

    }).error(function (err, status) { 
     _logOut(); 
     deferred.reject(err); 
    }); 

    return deferred.promise; 

}; 

var _logOut = function() { 

    $http.delete(serviceBase + 'api/authorization').success(function() { 
     localStorageService.remove('authorizationData'); 

     _authentication.isAuth = false; 
     _authentication.userName = ""; 
    }); 
}; 

var _fillAuthData = function() { 

    var authData = localStorageService.get('authorizationData'); 
    if (authData) { 
     _authentication.isAuth = true; 
     _authentication.userName = authData.userName; 
    } 

} 

authServiceFactory.saveRegistration = _saveRegistration; 
authServiceFactory.login = _login; 
authServiceFactory.logOut = _logOut; 
authServiceFactory.fillAuthData = _fillAuthData; 
authServiceFactory.authentication = _authentication; 

return authServiceFactory; 
}]); 

Trong WebAPI:

using System.Collections.Generic; 
using System.Configuration; 
using System.IdentityModel.Protocols.WSTrust; 
using System.IdentityModel.Services; 
using System.IdentityModel.Tokens; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Security.Claims; 
using System.ServiceModel; 
using System.ServiceModel.Description; 
using System.ServiceModel.Security; 
using System.Web.Http; 
using System.Xml; 
using Thinktecture.IdentityModel.Constants; 
using Thinktecture.IdentityModel.WSTrust; 
using WebApi_AngularJs.Model; 

namespace WebApi_AngularJs.Controllers 
{ 
    public class AuthorizationController : ApiController 
    { 
     // GET: api/Authorization 
     public IEnumerable<string> Get() 
     { 
      return new string[] { "value1", "value2" }; 
     } 

     // GET: api/Authorization/5 
     [Authorize] 
     public string Get(int id) 
     { 
      return "value"; 
     } 

    // POST: api/Authorization 
    public LoginResponse Post([FromBody]Login data) 
    { 
     var credentials = new ClientCredentials(); 
     credentials.UserName.UserName = data.UserName; 
     credentials.UserName.Password = data.Password; 

     ServicePointManager.ServerCertificateValidationCallback = (obj, certificate, chain, errors) => true; 

     var claims = GetClaimsFromIdentityServer(data.UserName, data.Password); 

     var response = new LoginResponse(); 
     if (claims != null) 
     { 
      //All set so now create a SessionSecurityToken 
      var token = new SessionSecurityToken(claims) 
      { 
       IsReferenceMode = true //this is 
       //important.this is how you say create 
       //the token in reference mode meaning 
       //your session cookie will contain only a 
       //referenceid(which is very small) and 
       //all claims will be stored on the server 
      }; 
      FederatedAuthentication.WSFederationAuthenticationModule. 
      SetPrincipalAndWriteSessionToken(token, true); 

      response = new LoginResponse { access_token = token.Id , data = "data"}; 
     } 

     return response; 
    } 

    // PUT: api/Authorization/5 
    public void Put(int id, [FromBody]string value) 
    { 
    } 

    // DELETE: api/Authorization/ 
    public void Delete() 
    { 
     //clear local cookie 
     FederatedAuthentication.SessionAuthenticationModule.SignOut(); 
     FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie(); 
     FederatedAuthentication.WSFederationAuthenticationModule.SignOut(false); 
    } 

    private ClaimsPrincipal GetClaimsFromIdentityServer(string username, string password) 
    { 
     const string WS_TRUST_END_POINT = "https://srv:4443/issue/wstrust/mixed/username"; 
     var factory = new System.ServiceModel.Security.WSTrustChannelFactory 
     (new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), 
            string.Format(WS_TRUST_END_POINT)); 
     factory.TrustVersion = TrustVersion.WSTrust13; 
     factory.Credentials.UserName.UserName = username; 
     factory.Credentials.UserName.Password = password; 

     var rst = new System.IdentityModel.Protocols.WSTrust.RequestSecurityToken 
     { 
      RequestType = RequestTypes.Issue, 
      KeyType = KeyTypes.Bearer, 
      TokenType = TokenTypes.Saml2TokenProfile11, 
      AppliesTo = new EndpointReference 
      ("urn:webapisecurity") 
     }; 
     var st = factory.CreateChannel().Issue(rst); 
     var token = st as GenericXmlSecurityToken; 
     var handlers = FederatedAuthentication.FederationConfiguration. 
     IdentityConfiguration.SecurityTokenHandlers; 
     var token = handlers.ReadToken(new XmlTextReader 
     (new StringReader(token.TokenXml.OuterXml))) as Saml2SecurityToken; 
     var identity = handlers.ValidateToken(token).First(); 
     var principal = new ClaimsPrincipal(identity); 
     return principal; 
    } 
} 
} 

Trong Web.Config:

<?xml version="1.0" encoding="utf-8"?> 
<!-- 
    For more information on how to configure your ASP.NET application, please visit 
    http://go.microsoft.com/fwlink/?LinkId=301879 
    --> 
<configuration> 
    <configSections> 
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> 
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> 
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> 
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 
    </configSections> 
    <appSettings> 
    <add key="webpages:Version" value="3.0.0.0" /> 
    <add key="webpages:Enabled" value="false" /> 
    <add key="ClientValidationEnabled" value="true" /> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true" /> 
    <add key="ida:FederationMetadataLocation" value="https://srv:4443/FederationMetadata/2007-06/FederationMetadata.xml" /> 
    <add key="ida:Realm" value="urn:webapisecurity" /> 
    <add key="ida:AudienceUri" value="urn:webapisecurity" /> 
    <add key="AppName" value="Web API Security Sample" /> 
    </appSettings> 
    <system.web> 
    <compilation debug="true" targetFramework="4.5" /> 
    <httpRuntime targetFramework="4.5" /> 
    </system.web> 
    <system.webServer> 
    <handlers> 
     <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 
     <remove name="OPTIONSVerbHandler" /> 
     <remove name="TRACEVerbHandler" /> 
     <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 
    </handlers> 
    <modules> 
     <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" /> 
     <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" /> 
    </modules> 
    <validation validateIntegratedModeConfiguration="false" /> 
    </system.webServer> 
    <system.identityModel> 
    <identityConfiguration> 
     <audienceUris> 
     <add value="urn:webapisecurity" /> 
     </audienceUris> 
     <claimsAuthorizationManager type="Thinktecture.IdentityServer.Ofi.AuthorizationManager, Thinktecture.IdentityServer.Ofi, Version=1.0.0.0, Culture=neutral" /> 
     <claimsAuthenticationManager type="Thinktecture.IdentityServer.Ofi.AuthenticationManager, Thinktecture.IdentityServer.Ofi, Version=1.0.0.0, Culture=neutral" /> 
     <certificateValidation certificateValidationMode="None" /> 
     <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <trustedIssuers> 
      <add thumbprint="489116B0FCF14DF66D47AE272C3B9FD867D0E050" /> 
     </trustedIssuers> 
     </issuerNameRegistry> 
    </identityConfiguration> 
    </system.identityModel> 
    <system.identityModel.services> 
    <federationConfiguration> 
     <cookieHandler requireSsl="false" /> 
     <wsFederation passiveRedirectEnabled="true" issuer="https://srv:4443/issue/wsfed" realm="urn:webapisecurity" reply="http://localhost:64346/" requireHttps="false" /> 
    </federationConfiguration> 
    </system.identityModel.services> 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" /> 
     <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" /> 
     <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> 
     <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> 
     <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> 
     <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" /> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
    <entityFramework> 
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> 
    <providers> 
     <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> 
    </providers> 
    </entityFramework> 
</configuration> 

Với điều này, tôi có thể thấy đầu bếp FedAuth tức là thiết lập trong trình duyệt và nó làm cho xác nhận trong WebApi quá.

+0

Yea này cũng hoạt động, giải pháp tôi đưa ra tuy nhiên là phù hợp hơn nếu bạn muốn SSO. –

+0

Cảm ơn bạn đã gửi bài giải pháp của bạn. Điều này đã giúp tôi allot !! Nó cũng đăng nhập tốt đẹp thông qua một proxy thay vì chuyển hướng đến Idsrv. Một lần nữa, cảm ơn bạn. – StefanHa

+0

Rất vui được giúp bạn! – cdiazal

6

Có một vài điều bạn cần làm. Tạo ứng dụng khách OAuth sẽ thực hiện yêu cầu mã thông báo và sử dụng để nhận mã thông báo truy cập từ máy chủ nhận dạng cho phép bạn truy cập vào các điểm cuối api trên web của mình. Để thực hiện điều này, ứng dụng khách OAuth của bạn cần phải bật luồng ngầm. Sau đó bạn thực hiện yêu cầu đăng nhập vào máy chủ Identity, thường thông qua cửa sổ bật lên để cho phép ứng dụng OAuth của bạn đăng nhập. Bạn cần chuyển chi tiết khách hàng OAuth của mình vào chuỗi truy vấn của yêu cầu đăng nhập Idsrv, cấu hình ứng dụng khách OAuth sẽ là những gì bạn đã định nghĩa trong bảng quản trị Idsrv của bạn cho khách hàng OAuth, bạn sẽ parameterize đó và gắn nó vào url OAuth2/authorzie:

getIdpOauthEndpointUrl: function() { 
       return "https://192.168.1.9/issue/oauth2/authorize"; 
}, 
getOAuthConfig: function() { 
       return { 
        client_id: "Your Oauth CLient ID that you specifie din Identity Server", 
        scope: "The scope of your RP", 
        response_type: "token", 
        redirect_uri: "https://..YourAngularAppUrl/AuthCallback.html" 
       }; 
} 

sau đó bạn mở cửa sổ đăng nhập:

var url = authService.getIdpOauthEndpointUrl() + "?" + $.param(authService.getOAuthConfig()); 
        window.open(url, "Login", "height=500,width=350"); 

Trong ứng dụng khách OAuth của bạn trongIdsrv, bạn cần chỉ định URL chuyển hướng, trong trường hợp của chúng tôi:

https://YourAngularAppUrl/AuthCallback.html 

đó là những gì bạn chuyển vào yêu cầu đăng nhập vào máy chủ nhận dạng cùng với chi tiết khách hàng OAuth của bạn. Trang AuthCallback.html không có gì ngoài việc trích xuất mã thông báo truy cập được trả về bởi idsrv đến trang đó trong chuỗi truy vấn và chuyển nó vào ứng dụng góc của bạn, cách bạn thực hiện điều đó tùy thuộc vào bạn, nhưng mã thông báo truy cập đó cần được đưa vào tiêu đề $http của bạn .

Các access token có thể được chiết xuất trong trang AuthCallback.html của bạn như thế này:

<script src="/Scripts/jquery-2.0.3.js"></script> 
<script src="/Scripts/jquery.ba-bbq.min.js"></script> 

<script type="text/javascript"> 
    var params = $.deparam.fragment(location.hash.substring(1)); 

    window.opener.oAuthCallback(params); 
    window.close(); 
</script> 

chức năng OAuthCallback được định nghĩa trong trang vỏ của tôi, index.html của tôi và có trách nhiệm đi qua các dấu hiệu nó đưa vào ứng dụng góc cạnh của tôi và đặt nó vào các tiêu đề $http.

function oAuthCallback(OAUTHTOKEN) { 
    angular.element(window.document).scope().setHttpAuthHeaderAndAuthenticate(OAUTHTOKEN); 
} 

Chức năng setHttpAuthHeaderAndAuthenticate() được định nghĩa trên $rootScope của tôi, và nó đặt mã thông báo vào các tiêu đề $http authorizaiton:

$http.defaults.headers.common.Authorization = 'Bearer ' + OAUTHTOKEN["access_token"];

Có một cái nhìn tại this post Christian Weyer Nó thực hiện chính xác những gì chúng tôi đang làm, nhưng đó là một ứng dụng knockout/web-api, cùng một khái niệm vẫn còn.

Bước tiếp theo là yêu cầu api web của bạn chấp nhận mã thông báo truy cập từ idsrv, điều này rất đơn giản;

public static void Configure(HttpConfiguration config) 
     { 
      var authConfig = new AuthenticationConfiguration(); 

      authConfig.AddJsonWebToken(
    YourIdsrvSiteId, YourRpsScope/Relam,YourRpsSymmetricSigningKey 
); 

      config.MessageHandlers.Add(new AuthenticationHandler(authNConfig)); 
     } 

Bạn cũng có thể xác định một ClaimsAuthenticationManager và ClaimsAuthorizationManager đây để cho phép bạn chuyển đổi các yêu cầu và Grant/Deny acces sto các tài nguyên web api. Một lần nữa, điều này được đề cập trong bài đăng của Christian Weyer. Hi vọng điêu nay co ich.

+0

Tôi cũng sẽ thử cách này, rất nhiều thứ để tìm hiểu! Cảm ơn bạn! – cdiazal

Các vấn đề liên quan