Class: AtprotoAuth::State::SessionManager

Inherits:
Object
  • Object
show all
Defined in:
lib/atproto_auth/state/session_manager.rb

Overview

Manages active OAuth sessions with secure persistent storage

Instance Method Summary collapse

Constructor Details

#initializeSessionManager

Returns a new instance of SessionManager.



7
8
9
# File 'lib/atproto_auth/state/session_manager.rb', line 7

def initialize
  @serializer = Serialization::Session.new
end

Instance Method Details

#cleanup_expiredvoid

This method returns an undefined value.

Removes all expired sessions



117
118
119
# File 'lib/atproto_auth/state/session_manager.rb', line 117

def cleanup_expired
  # No-op - expiry handled by storage TTL and retrieval validation
end

#create_session(client_id:, scope:, auth_server: nil, did: nil) ⇒ Session

Creates and stores a new session

Parameters:

  • client_id (String)

    OAuth client ID

  • scope (String)

    Requested scope

  • auth_server (AuthorizationServer, nil) (defaults to: nil)

    Optional pre-resolved auth server

  • did (String, nil) (defaults to: nil)

    Optional pre-resolved DID

Returns:

  • (Session)

    The created session



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/atproto_auth/state/session_manager.rb', line 17

def create_session(client_id:, scope:, auth_server: nil, did: nil)
  session = Session.new(
    client_id: client_id,
    scope: scope,
    auth_server: auth_server,
    did: did
  )

  # Store both session and state mapping atomically
  session_key = Storage::KeyBuilder.session_key(session.session_id)
  state_key = Storage::KeyBuilder.state_key(session.state_token)

  AtprotoAuth.storage.with_lock(session_key, ttl: 30) do
    serialized = @serializer.serialize(session)
    AtprotoAuth.storage.set(session_key, serialized)
    AtprotoAuth.storage.set(state_key, session.session_id)
  end

  session
end

#get_session(session_id) ⇒ Session?

Retrieves a session by ID

Parameters:

  • session_id (String)

    Session ID to look up

Returns:

  • (Session, nil)

    The session if found



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/atproto_auth/state/session_manager.rb', line 58

def get_session(session_id)
  session_key = Storage::KeyBuilder.session_key(session_id)

  begin
    serialized = AtprotoAuth.storage.get(session_key)
    return nil unless serialized
  rescue StandardError => e
    AtprotoAuth.configuration.logger.error("Failed to get session: #{e.message}")
    return nil
  end

  begin
    session = @serializer.deserialize(serialized)
    return nil if !session.renewable? && session.tokens&.expired?

    session
  rescue StandardError => e
    AtprotoAuth.configuration.logger.error("Failed to deserialize session: #{e.message}")
    nil
  end
end

#get_session_by_state(state) ⇒ Session?

Finds a session by state token

Parameters:

  • state (String)

    State token to look up

Returns:

  • (Session, nil)

    The session if found



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/atproto_auth/state/session_manager.rb', line 83

def get_session_by_state(state)
  return nil unless state

  state_key = Storage::KeyBuilder.state_key(state)

  begin
    session_id = AtprotoAuth.storage.get(state_key)
    return nil unless session_id
  rescue StandardError => e
    AtprotoAuth.configuration.logger.error("Failed to get session by state: #{e.message}")
    return nil
  end

  get_session(session_id)
end

#remove_session(session_id) ⇒ void

This method returns an undefined value.

Removes a session

Parameters:

  • session_id (String)

    Session ID to remove



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/atproto_auth/state/session_manager.rb', line 102

def remove_session(session_id)
  session = get_session(session_id)
  return unless session

  session_key = Storage::KeyBuilder.session_key(session_id)
  state_key = Storage::KeyBuilder.state_key(session.state_token)

  AtprotoAuth.storage.with_lock(session_key, ttl: 30) do
    AtprotoAuth.storage.delete(session_key)
    AtprotoAuth.storage.delete(state_key)
  end
end

#update_session(session) ⇒ Session

Updates an existing session

Returns:

  • (Session)

    The session to update

  • (Session)

    The updated session



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/atproto_auth/state/session_manager.rb', line 41

def update_session(session)
  session_key = Storage::KeyBuilder.session_key(session.session_id)

  AtprotoAuth.storage.with_lock(session_key, ttl: 30) do
    serialized = @serializer.serialize(session)
    AtprotoAuth.storage.set(session_key, serialized)

    state_key = Storage::KeyBuilder.state_key(session.state_token)
    AtprotoAuth.storage.set(state_key, session.session_id)
  end

  session
end