Davidsual / IdentityServer3_WebApi_AngularJs_SSO_BearerToken

IdentityServer3 + WebApi + AngularJs + SSO + BearerToken stored in HTTPS cookie
3 stars 3 forks source link

Missing project in this repository called Core #1

Open Jenanek opened 9 years ago

Jenanek commented 9 years ago

Hi David, I have found your repository about combination identity server v3 with angular but your repository is not completed to work. Do you have working solution for public?

Thanks J

Davidsual commented 9 years ago

Hi,

My repository are normally proof of concept for my work challenges.

I almost complete the SSO (token based) with latest version of identity server integrated with web.api.

In the next week the architecture will be treated by penetration testers. Once is stable I will publish on github.

If you have some particular question do not hesitate to ask, I spent hours in prototypes for identity server 3 token based.

Davide

Jenanek commented 9 years ago

Hi David, Thank you for your reply.

Now I need help with oidc-token-manager.js and setting attribute silent_renew, do you know how does it work?

Thank you J.

Davidsual commented 9 years ago

No I am using a different approach... I store token in a cookie (for avoiding to store the token in Local/session storage because XSS attack). The HTML perform requests to Web.Api 2 and an OwinMiddleware is checking if the token is present in the cookie. Every time that Angualrjs performs a GET or POST in an ACTION marked AUTHORIZED the Web.API2 asks IDS to Validate the TOKEN

Jenanek commented 9 years ago

It sounds great.

Please, can you add the part of code where you setting OwinMiddleware for behavior wich you descripted above?

Thank you. J.

Davidsual commented 9 years ago

Steps: 1) AngularJs Post USERNAME/PASSWORD 2) Verify against IDS if is ok IDS will return AccessToken / RefreshToken. Those two string are stored in a cookie (Secure cookie). Controller return 200 to Angularjs. 3) For each consecutive requests angularjs doesn't care about passing token...

OwinMiddleware check if in the request there is a cookie... and if in the cookie there is the token.

public sealed class TrackingMiddleware : OwinMiddleware
    {
        public TrackingMiddleware(OwinMiddleware next)
            : base(next)
        {
        }

        public override async System.Threading.Tasks.Task Invoke(IOwinContext context)
        {

            //var cookie = context.Request.Headers.GetCookies("tes").SingleOrDefault();

            //if (cookie != null && cookie.Cookies.Any() && !string.IsNullOrEmpty(cookie.Cookies[0].Value))
            //    context.Request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", cookie.Cookies[0].Value);

            if(context.Request.Method != "OPTIONS" && context.Request.Cookies.Any())
            {
                var cookie = context.Request.Cookies["tes"];
                if (!string.IsNullOrEmpty(cookie))
                {
                    context.Request.Headers.Remove("Authorization");
                    context.Request.Headers.Add("Authorization", new[] { "Bearer " + cookie }); //.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", cookie.Cookies[0].Value);
                }
            }

            await Next.Invoke(context);
        }
    }

The code add in the request in the tag Authorization the value of the token stored in the cookie. The tag [AUTHORIZED] above every controller / action will work as usual..

Does it make sense?

I will post in the next week all the code for doing that IDS 3 + Asp.Net Identity 2.0 --> integrated with Web.Api 2 with frontend AngularJs

Jenanek commented 9 years ago

Thank you for your quick reply.

Where can I fill this cookie with access token and refresh token?

J.

Davidsual commented 9 years ago

Hi below an example.

        [HttpPost]
        [Route("login")]
        [AllowAnonymous]
        public HttpResponseMessage Login([FromBody] LoginViewModel input)
        {
            var client = new OAuth2Client(
                    new Uri("https://MyIDS3ServerName:44333/connect/token"),
                    "clientid",
                    "21B5F798-BE55-42BC-8AA8-0025B903DC3B");
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

            var response = client.RequestResourceOwnerPasswordAsync(input.Username, input.Password, "api1 api2 offline_access").Result;

            var response2 = new HttpResponseMessage(HttpStatusCode.OK);

            var cookie = new CookieHeaderValue("Davide-Secure", response.AccessToken);
            cookie.Expires = DateTimeOffset.Now.AddMinutes(1);
            cookie.Domain = null;//Request.RequestUri.Host;
            cookie.Path = "/";
            cookie.HttpOnly = true;            
            cookie.Secure = true;        
            response2.Headers.AddCookies(new CookieHeaderValue[] { cookie });

            return response2;            
        }

In this scenario... AngularJs asks to login to Web.Api posting username password. Web.Api2 that doesn't know anything about login redirect the request to IDS3

Identity server verify everything, and if ok will return 2 tokens... refresh / access token. You simply put these two strings in a secure cookie.

Jenanek commented 9 years ago

Are these settings of cookies in API project?

I'm wondering still about where I need create then settings of cookies.

Where I call class TrackingMiddleware?

Thank you very much David.

Davidsual commented 9 years ago

Cookie setting can be set in Web/App.Config or in the code but remember to set these two values because in this way you secure your cookie preventing to be changed by javascript

            cookie.HttpOnly = true;            
            cookie.Secure = true;    

TrackingMiddleware need to be registered in Startup class... it becomes part of the request pipeline... you do not have to call it... it is invoke for each request.. (like a filter for example).

Jenanek commented 9 years ago

David thank you very much for your comments.

Can I use following scenario? ->

1.) Create IdentityServerv3 on first project => configuration users, claims etc. - Allow clients "Api1"

2.) Create WebApi Project (as Resource Server) called "Api1" and include something like your class - "TrackingMiddleware"

3.) Create frontend with AngularJS and include WebApi and create in this project a WebApi Controller called for example AccountController and insert your method "public HttpResponseMessage Login([FromBody] LoginViewModel input)" => RUN all solution

4.) Open frontend website -> go to login page -> send via ajax request login and password => Login method return HttpResponseMessage with cookie with headers. These headers return bearer token with access token - is it true?

5.) Now I can create a http request to Resource Server -> to for example OrdersControllers => middlewere provides pass cookie with access token - is it true?

I'm trying to understand this flow.

Thank you. J.

Davidsual commented 9 years ago

Hi

below is how I structured my solution 1) window service (TopShelf) that hosts IDS 3 + integration with Asp.Net Identity 2.0 2) Web Application Owin - Web.Api 2 that is the service layer for your client html (with of course owinmiddleware for checking if cookie is present) 3) Html website AngularJs that talks just with web.api 2

Website perform a POST request with credential (username/password) to Web.Api2 Web.Api2 using OAuth2Client (provided by Ids3) talks with IDS3 asking if the credential are correct... if yes...IDS3 will return two tokens... Web.Api2 before return OK to Angularjs creates a cookie and stores inside the two tokens. Client Angularjs receive as response 200 OK and can carry on with consecutive requests.. passing in the request header the cookie. (that contains token).

Jenanek commented 9 years ago

David, thank you very much for your comments.

I look forward to your final code after penetration tests.

I follow your repository and next commit I am going to try very soon. :-)

Have a nice day. J.

Jenanek commented 9 years ago

Davide, I have one question yet.

Where is the store cookie when I set HTTP-ONLY? Thanks. J.

Jenanek commented 8 years ago

Hi David,

how do you continue with your project?

I check your repository and without changes. :-)

Will you commit any changes? I am looking forward to do this.

J.