diff --git a/aiohttp_security/__init__.py b/aiohttp_security/__init__.py
index dc1bab8..572237a 100644
--- a/aiohttp_security/__init__.py
+++ b/aiohttp_security/__init__.py
@@ -1,5 +1,5 @@
 from .abc import AbstractIdentityPolicy, AbstractAuthorizationPolicy
-from .api import remember, forget, setup, authorize, permits
+from .api import remember, forget, setup, authorize, permits, get_user_identity
 from .cookies_identity import CookiesIdentityPolicy
 from .session_identity import SessionIdentityPolicy
 
@@ -9,4 +9,5 @@ __version__ = '0.1.0'
 
 __all__ = ('AbstractIdentityPolicy', 'AbstractAuthorizationPolicy',
            'CookiesIdentityPolicy', 'SessionIdentityPolicy',
-           'remember', 'forget', 'authorize', 'permits', 'setup')
+           'remember', 'forget', 'authorize', 'permits',
+           'get_user_identity', 'setup')
diff --git a/aiohttp_security/api.py b/aiohttp_security/api.py
index d1c5051..a3607a6 100644
--- a/aiohttp_security/api.py
+++ b/aiohttp_security/api.py
@@ -1,6 +1,8 @@
 import asyncio
 import functools
+
 from aiohttp import web
+
 from aiohttp_security.abc import (AbstractIdentityPolicy,
                                   AbstractAuthorizationPolicy)
 
@@ -16,18 +18,34 @@ def authorize(required=True, redirect_url=None, permission=None):
             # assuming first argument is request
             assert isinstance(args[0], web.Request)
             request = args[0]
+
+            # check if coroutine
             if asyncio.iscoroutinefunction(f):
                 coro = f
             else:
                 coro = asyncio.coroutine(f)
-            identity = yield from get_user_identity(request)
-            if not identity and required:
-                raise web.HTTPForbidden()
-            kwargs['identity'] = identity
-            return (yield from coro(*args, **kwargs))
-        return wrapped
-    return wrapper
 
+            # get identity
+            identity = yield from get_user_identity(request)
+            kwargs['identity'] = identity
+
+            if required:
+
+                # check identity
+                if not identity:
+                    return web.HTTPFound(redirect_url) if redirect_url \
+                        else web.HTTPForbidden(reason='not authenticated')
+
+                # check permission
+                allowed = yield from permits(request, permission)
+                if permission and not allowed:
+                    return web.HTTPForbidden(reason='unauthorized')
+
+            return (yield from coro(*args, **kwargs))
+
+        return wrapped
+
+    return wrapper
 
 
 @asyncio.coroutine
@@ -78,6 +96,7 @@ def get_user_identity(request):
     identity = yield from identity_policy.identify(request)
     return identity
 
+
 '''
 @asyncio.coroutine
 def authorized_userid(request):
@@ -98,6 +117,8 @@ def permits(request, permission, context=None):
     assert isinstance(permission, str), permission
     assert permission
     autz_policy = request.app.get(AUTZ_KEY)
+    if autz_policy is None:
+        return True
     identity = yield from get_user_identity(request)
     access = yield from autz_policy.permits(identity, permission, context)
     return access
diff --git a/demo/session_auth/auth_policy.py b/demo/session_auth/auth_policy.py
new file mode 100644
index 0000000..953ebd7
--- /dev/null
+++ b/demo/session_auth/auth_policy.py
@@ -0,0 +1,11 @@
+import asyncio
+
+from aiohttp_security.abc import AbstractAuthorizationPolicy
+
+
+class StubAuthorizationPolicy(AbstractAuthorizationPolicy):
+    @asyncio.coroutine
+    def permits(self, identity, permission, context=None):
+        if identity == permission:
+            return True
+        return False
diff --git a/demo/session_auth/handlers.py b/demo/session_auth/handlers.py
new file mode 100644
index 0000000..a6a4fbf
--- /dev/null
+++ b/demo/session_auth/handlers.py
@@ -0,0 +1,34 @@
+from aiohttp import web
+from aiohttp_jinja2 import render_template
+
+from aiohttp_security import authorize, get_user_identity, remember, forget
+
+
+@authorize(required=True, redirect_url='/login', permission='Steve')
+async def index(request, identity=None):
+    context = {'name': identity}
+    response = render_template('index.html', request, context)
+    return response
+
+
+async def login(request):
+    identity = await get_user_identity(request)
+    if identity:
+        return web.HTTPFound('/')
+    response = render_template('login.html', request, {})
+    return response
+
+
+async def login_post(request):
+    post_data = await request.post()
+    user_id = post_data['username']
+    password = post_data['password']
+    response = web.Response(body=b'OK')
+    await remember(request, response, user_id)
+    return response
+
+
+async def logout(request):
+    response = web.Response(body=b'OK')
+    await forget(request, response)
+    return response
diff --git a/demo/session_auth/main.py b/demo/session_auth/main.py
new file mode 100644
index 0000000..38e0508
--- /dev/null
+++ b/demo/session_auth/main.py
@@ -0,0 +1,27 @@
+import asyncio
+import os
+
+import jinja2
+from aiohttp import web
+from aiohttp_jinja2 import setup as setup_jinja
+from aiohttp_session import setup as setup_session
+from aiohttp_session.redis_storage import RedisStorage
+from aioredis import create_pool
+
+from aiohttp_security import setup as setup_security, SessionIdentityPolicy
+from .auth_policy import StubAuthorizationPolicy
+from .handlers import index, login, login_post, logout
+
+loop = asyncio.get_event_loop()
+redis_pool = loop.run_until_complete(create_pool(('localhost', 6379)))
+app = web.Application(loop=loop)
+setup_session(app, RedisStorage(redis_pool))
+setup_security(app,
+               SessionIdentityPolicy(),
+               StubAuthorizationPolicy())
+setup_jinja(app, loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
+app.router.add_route('GET', '/', index)
+app.router.add_route('GET', '/login', login)
+app.router.add_route('POST', '/login', login_post)
+app.router.add_route('GET', '/logout', logout)
+web.run_app(app)
diff --git a/demo/session_auth/templates/base.html b/demo/session_auth/templates/base.html
new file mode 100644
index 0000000..0e9ee8e
--- /dev/null
+++ b/demo/session_auth/templates/base.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>aiohttp_security demo</title>
+</head>
+<body>
+{% block content %}{% endblock %}
+{% block script %}{% endblock %}
+</body>
+</html>
\ No newline at end of file
diff --git a/demo/session_auth/templates/index.html b/demo/session_auth/templates/index.html
new file mode 100644
index 0000000..71135e5
--- /dev/null
+++ b/demo/session_auth/templates/index.html
@@ -0,0 +1,6 @@
+{% extends 'base.html' %}
+{% block content %}
+<div>
+    <h1>Hello {{name}}!</h1>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/demo/session_auth/templates/login.html b/demo/session_auth/templates/login.html
new file mode 100644
index 0000000..1f664a2
--- /dev/null
+++ b/demo/session_auth/templates/login.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% block content %}
+<div>
+    <h3>Login</h3>
+    <form class="m-t" role="form" action="/login" method="post">
+        <div class="form-group">
+            <input name="username" type="text" class="form-control" placeholder="ID" required="">
+        </div>
+        <div class="form-group">
+            <input name="password" type="password" class="form-control" placeholder="Password" required="">
+        </div>
+        <button type="submit">Login</button>
+    </form>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/tests/test_cookies_identity.py b/tests/test_cookies_identity.py
index 59a691f..d58e36b 100644
--- a/tests/test_cookies_identity.py
+++ b/tests/test_cookies_identity.py
@@ -15,10 +15,6 @@ class Autz(AbstractAuthorizationPolicy):
     def permits(self, identity, permission, context=None):
         pass
 
-    @asyncio.coroutine
-    def authorized_userid(self, identity):
-        pass
-
 
 @pytest.mark.run_loop
 def test_remember(create_app_and_client):
diff --git a/tests/test_dict_autz.py b/tests/test_dict_autz.py
index cef2e41..0733c1c 100644
--- a/tests/test_dict_autz.py
+++ b/tests/test_dict_autz.py
@@ -2,8 +2,7 @@ import asyncio
 import pytest
 
 from aiohttp import web
-from aiohttp_security import (remember,
-                              authorized_userid, permits,
+from aiohttp_security import (remember, permits, get_user_identity,
                               AbstractAuthorizationPolicy)
 from aiohttp_security import setup as _setup
 from aiohttp_security.cookies_identity import CookiesIdentityPolicy
@@ -18,12 +17,14 @@ class Autz(AbstractAuthorizationPolicy):
         else:
             return False
 
+    '''
     @asyncio.coroutine
     def authorized_userid(self, identity):
         if identity == 'UserID':
             return 'Andrew'
         else:
             return None
+    '''
 
 
 @pytest.mark.run_loop
@@ -32,12 +33,12 @@ def test_authorized_userid(create_app_and_client):
     @asyncio.coroutine
     def login(request):
         response = web.HTTPFound(location='/')
-        yield from remember(request, response, 'UserID')
+        yield from remember(request, response, 'Andrew')
         return response
 
     @asyncio.coroutine
     def check(request):
-        userid = yield from authorized_userid(request)
+        userid = yield from get_user_identity(request)
         assert 'Andrew' == userid
         return web.Response(text=userid)
 
@@ -58,7 +59,7 @@ def test_authorized_userid_not_authorized(create_app_and_client):
 
     @asyncio.coroutine
     def check(request):
-        userid = yield from authorized_userid(request)
+        userid = yield from get_user_identity(request)
         assert userid is None
         return web.Response()
 
diff --git a/tests/test_no_auth.py b/tests/test_no_auth.py
index 8c3d99e..cb0dfeb 100644
--- a/tests/test_no_auth.py
+++ b/tests/test_no_auth.py
@@ -2,7 +2,7 @@ import asyncio
 import pytest
 
 from aiohttp import web
-from aiohttp_security import authorized_userid, permits
+from aiohttp_security import permits, get_user_identity
 
 
 @pytest.mark.run_loop
@@ -10,7 +10,7 @@ def test_authorized_userid(create_app_and_client):
 
     @asyncio.coroutine
     def check(request):
-        userid = yield from authorized_userid(request)
+        userid = yield from get_user_identity(request)
         assert userid is None
         return web.Response()
 
diff --git a/tests/test_session_identity.py b/tests/test_session_identity.py
index d133ea6..06cf1c3 100644
--- a/tests/test_session_identity.py
+++ b/tests/test_session_identity.py
@@ -17,10 +17,6 @@ class Autz(AbstractAuthorizationPolicy):
     def permits(self, identity, permission, context=None):
         pass
 
-    @asyncio.coroutine
-    def authorized_userid(self, identity):
-        pass
-
 
 @pytest.fixture
 def create_app_and_client2(create_app_and_client):