Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

persistent Session DB storage #435

Closed
taskoma opened this issue Oct 27, 2017 · 11 comments
Closed

persistent Session DB storage #435

taskoma opened this issue Oct 27, 2017 · 11 comments

Comments

@taskoma
Copy link

taskoma commented Oct 27, 2017

Good day,
for now SessionDB in-memory solution, this mean that after application restart all "authorized" users flush and need again pass authorization.

What is right way to support persistent storage? Or maybe there are any "ready to use" solutions?

@decentral1se
Copy link
Contributor

Hi @taskoma, you need to adapt the SessionDB to use a data store of your choice underneath. This is really unfortunate to not have inside the library and there is some talk between maintainers about providing a pre-built persistent sessionDB store. We didn't get there yet.

I've written a Redis one, so can provide portable code for that - which data store will you choose?

@decentral1se decentral1se added this to the Support milestone Oct 27, 2017
@taskoma
Copy link
Author

taskoma commented Oct 27, 2017

redis is good choice, if you can share you code it will help a lot :)

@decentral1se
Copy link
Contributor

OK, let's see now, here's what I had:

class RedisSessionDB(dict):
    """Dict interface for Redis session management."""
    def __init__(self, connection):
        self.connection = connection

    def keys(self):
        return self.connection.keys()

    def flushall(self):
        self.connection.flushall()

    def __getitem__(self, key):
        value = self.connection.get(key)
        if value is None:
            raise KeyError(key)
        utf8ified = str(value, "utf-8")
        return json.loads(utf8ified)

    def __setitem__(self, key, value):
        value = json.dumps(value)
        self.connection.set(key, value)

    def __contains__(self, item):
        return self.connection.exists(item)

    def __delitem__(self, key):
        self.connection.delete(key)

Let me know if that works!

@taskoma
Copy link
Author

taskoma commented Nov 28, 2017

@lwm thanks a lot, may be you can share example of using you code?
can't catch how to switch from class SessionDB(object):

@decentral1se
Copy link
Contributor

decentral1se commented Nov 29, 2017

No worries, it looks like I did:

    connection = Redis(host=host, port=port, db=db_num)
    redis_db = RedisSessionDB(connection)
    session_db = SessionDB("", db=redis_db)
    Provider(
        issuer,
        session_db,  # passed in here!
        client_db,
        auth_broker,
        user_info_store,
        authz_handler,
        verification_function,
    )

@taskoma
Copy link
Author

taskoma commented Dec 1, 2017

@lwm

2017-12-01 18:24:22 application     ERROR    <oic.utils.sdb.AuthnEvent object at 0x7f0f110a1c90> is not JSON serializable
Traceback (most recent call last):
  File "./server.py", line 538, in application
    return callback(environ, start_response)
  File "./server.py", line 415, in authorization
    self.oas.authorization_endpoint, logger=logger)
  File "/opt/py2staging/local/lib/python2.7/site-packages/oic-0.9.5.0-py2.7.egg/oic/utils/http_util.py", line 526, in wsgi_wrapper
    args = func(**kwargs)
  File "/opt/py2staging/local/lib/python2.7/site-packages/oic-0.9.5.0-py2.7.egg/oic/oic/provider.py", line 827, in authorization_endpoint
    sid = self.setup_session(areq, authnres["authn_event"], cinfo)
  File "/opt/py2staging/local/lib/python2.7/site-packages/oic-0.9.5.0-py2.7.egg/oic/oic/provider.py", line 692, in setup_session
    sid = self.sdb.create_authz_session(authn_event, areq, oidreq=oidc_req)
  File "/opt/py2staging/local/lib/python2.7/site-packages/oic-0.9.5.0-py2.7.egg/oic/utils/sdb.py", line 635, in create_authz_session
    self._db[sid] = _dic
  File "./server.py", line 95, in __setitem__
    value = json.dumps(value)
  File "/usr/lib64/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib64/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib64/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib64/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <oic.utils.sdb.AuthnEvent object at 0x7f0f110a1c90> is not JSON serializable

this is result of outdated source? I use source base that fetched before " [#387]: Refactored the oic.utils.sdb.SessionDB constructor API "
did it make influence and rootcause?

@decentral1se
Copy link
Contributor

this is result of outdated source?

Perhaps, although we have made frequent releases. You can try latest HEAD as well.

If you provide more information, perhaps raise another issue with the problem.

@schlenk
Copy link
Collaborator

schlenk commented Dec 1, 2017

Yes, AuthnEvent wasn't json serializable in older versions. Update.

@taskoma
Copy link
Author

taskoma commented Dec 2, 2017

@lwm, @schlenk thanks
thats mean quite a lot of custom changes I need migrate to new version, heh (normal configuration for OP, telegraf metrics support, etc :) )

@taskoma
Copy link
Author

taskoma commented Dec 2, 2017

@lwm finally I migrated to current version of codebase but anyway something go wrong

  1. I see items in redis with code, access_token, refresh_token after user initialization
  2. if not restart application all going well:
    I can receive user info and update access_token by refresh_token

in logs for user_info:

2017-12-02 21:23:40 _parse_request  DEBUG    Found 0 verify keys
2017-12-02 21:23:40 _do_user_info   DEBUG    access_token type: 'T'
2017-12-02 21:23:40 __getitem__     INFO     d689fdd47251980b2da6df1677e3d62e9b647196fa090e0e54c3cb76
  1. but after application restart I catch error "Invalid token" for same request as to point 2

in logs

2017-12-02 21:26:56 _parse_request  DEBUG    Found 0 verify keys

api response:

{
    "error_description": "Invalid Token",
    "error": "invalid_token"
}

and response for new acess_token

{
    "error_description": "Refresh token is expired",
    "error": "invalid_request"
}

@taskoma
Copy link
Author

taskoma commented Dec 2, 2017

answers

  1. about userinfo:
    need set same secret / password during sessionDb initialization

  2. about refresh_token:
    refresh_tokens stored separated, so need use same schema as to sessiondb and redis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants