6

로그인 및 암호를 ASP.NET WebApi 백엔드로 보내고이 사용자에게 Thinktecture로 로그인하는 AngularJs 웹을 만들려고합니다.Thinktecture로 AngularJs ASP.NET WebApi 인증

WS-Federation을 사용하는 다른 프로젝트 인 ASP.NET MVC에서 Thinktecture가 잘 작동합니다. 이제는 비슷한 일을하려고하지만 일부 구성 요소를 변경하려고합니다. 제대로 작동하지 않습니다.

어떻게하면 WebApi에서 userName과 password를 Thinktecture로 보내고 유효성을 검사 할 수 있습니까?

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; 
     } 

    } 
} 

고마워요!

답변

5

마지막으로, 많이 읽고 나는이이

WebApi에서
'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; 
}]); 

:있는 Web.Config에서

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; 
    } 
} 
} 

:

<?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> 

이것으로 FedAuth 요리사를 볼 수 있습니다. 즉 브라우저에서 설정하고 WebApi에서도 유효성 검사를 수행합니다.

+0

네,이게 너무 효과적입니다. SSO를 원한다면 제가 준 솔루션이 더 적합합니다. –

+0

솔루션을 게시 해 주셔서 감사합니다. 이것은 나에게 할당을 도왔다!! 그것도 Idsrv로 리디렉션하는 대신 프록시를 통해 로그인하는 것이 좋습니다. 다시 한 번 감사드립니다. – StefanHa

+0

당신을 도와 주어서 기쁘다! – cdiazal

6

해야 할 일이 몇 가지 있습니다. 토큰 요청을 할 OAuth 클라이언트를 생성하고이를 사용하여 웹 서버 api 끝점에 액세스 할 수 있도록 ID 서버에서 액세스 토큰을 가져옵니다. 이렇게하려면 OAuth 클라이언트에 암시 적 플로우가 활성화되어 있어야합니다. 일반적으로 OAuth 클라이언트가 로그인 할 수 있도록 팝업 창을 통해 Identity 서버에 로그인 요청을합니다. OAuth 클라이언트 구성 정보 인 Idsrv에 대한 로그인 요청의 쿼리 문자열에 OAuth 클라이언트 세부 정보를 전달해야합니다 당신은 OAuth 클라이언트에 대한 Idsrv 관리 패널에 정의 된 어떤 것, 그 매개 변수화하고 OAuth2를/authorzie의 URL에 추가합니다 :

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

:

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" 
       }; 
} 

당신은 다음 로그인 창을 엽니 다 OAuth 클라이언트에서 다음과 같이 리디렉션 URL을 지정해야합니다.

https://YourAngularAppUrl/AuthCallback.html 

OAuth 클라이언트 세부 정보와 함께 ID 서버에 대한 로그인 요청에 전달한 내용입니다. AuthCallback.html 페이지는 idsrv가 반환 한 액세스 토큰을 쿼리 문자열의 해당 페이지로 추출하고 각도 앱에 전달합니다. 어떻게 할 것인가는 당신에게 달려 있지만 액세스 토큰은 $http 헤더에 입력해야합니다 . 내 index.html을,

<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> 

OAuthCallback 기능이 내 껍질 페이지에 정의되어 있으며이로 주어진 것 토큰을 전달하는 책임이있다 :

액세스 토큰

이처럼 AuthCallback.html 페이지에서 추출 할 수 있습니다 내 각 애플 리케이션과 $http 헤더에 넣어.

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

setHttpAuthHeaderAndAuthenticate() 기능은 내 $rootScope에 정의되며, 그것은 $http authorizaiton 헤더에 토큰을두고 :

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

기독교 Weyer에 의해 this post에서보세요 그것은 우리가 '정확하게 수행 다시하고 있지만, 그것은 녹아웃/웹 API 애플 리케이션, 여전히 같은 개념이야.

다음 단계는 idsrv에서 액세스 토큰을 수락하도록 웹 API에 알리는 것입니다. 이는 간단합니다.

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

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

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

당신은 또한 당신이 주장을 변환 할 수 있도록 여기에 ClaimsAuthenticationManager과 ClaimsAuthorizationManager을 정의 할 수 있습니다 및 그랜트/웹 API를 자원 STO 대한 액세스를 거부합니다. 다시이 모든 것이 Christian Weyer의 글에서 다루어집니다. 희망이 도움이됩니다. AngularJS와에서

:

+0

나는이 방법을 너무 배우기 위해 많이 시도 할 것이다! 고맙습니다! – cdiazal