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

List endpoint for active sessions of authenticated user #101

Open
mariobodemann opened this issue Jan 22, 2023 · 39 comments · May be fixed by #228
Open

List endpoint for active sessions of authenticated user #101

mariobodemann opened this issue Jan 22, 2023 · 39 comments · May be fixed by #228
Labels
enhancement New feature or request QoD v0.11.0 Within scope for v0.11.0

Comments

@mariobodemann
Copy link
Contributor

mariobodemann commented Jan 22, 2023

Summary

Create a /get endpoint offering a paginated response of all sessions that the currently authenticated user created and are still active.

Context

While testing the APIs it might happen that the session id from a successful create request will get lost. In that case, there is no way to retrieve the created sessions: The /get endpoint only returns sessions whose ids are known, but not all active ones for the authenticated user.

Proposal

Add a variant of the /get endpoint that takes optionally page information to return all sessions for the authenticated user. We optionally need pagination information, since more sessions might be available then we can return (think response size limits etc). Therefore this endpoint must be paginated.

The default values for the paginated parameters current page would be set to 0 and the size of a page to 100. So on average no page information is needed, but for heavy users, it is available.

The sorting of the response could be by it's startedAt field: sessions created early should appear before later sessions.

cURL example

This is an example of the proposed endpoint:

A call like

curl --request GET '{{baseUrl}}/sessions?page=4&pageSize=10' --header 'Authorization: <token>'

would return

{
  "pageSize": 10,
  "pageNumber": 4,
  "sessions": [
    {
      "id": "f0a49ce4-bda0-76eb-879c-3f19db88e985",
      "qos": "QOS_M",
      "ueId": {
         /// ....
      },
      "asId": {
         /// ....
      },
      "duration": 10
      "expiresAt": 1639566000,
      "startedAt": 1639479600,
    },
    /// 9 more sessions
  ]
}

Alternatives

A) One of the main reason for this proposal is the inability to find created sessions. This mostly stems from testing and due to user error the session id cannot be retrieved from the initial create request. In order to not block the ue and only create the needed amount of sessions, the default of the duration parameter could be set to a very low value: a 10 seconds duration would be deleting the session after 10 seconds, without the need to delete a session without the session id.

B) A second alternative could be to add a delete all endpoint: With this endpoint, we would not give out the session information, but could guarantee in an error case, there is the ability to delete existing sessions.

Initial Specification Proposal

Under #100 you can find an initial draft of a proposal on how the specification would need to change. (closed now, till a decisions on this issue is found)

@jlurien
Copy link
Collaborator

jlurien commented Jan 23, 2023

It is true that without the session id it is not possible to get info about or delete a session, and there is no way currently to discover it, so an GET /sessions endpoint would make sense.

With client_credentials, a client may have many sessions and in that case pagination would make sense, or alternative some support for filtering (for example based on ueId), or both. There are some guidelines proposed, but they may require some refinement as I think no CAMARA API has added these type of parameters yet.

If the main driver is to delete sessions without knowing the session id, another possibility is to allow a DELETE /sessions with filtering support to delete only a subset of sessions for that client, for example by ueId.

@mariobodemann
Copy link
Contributor Author

Thank you for the feedback.

I think it is a great idea to refine the suggestion to use the pagination parameters as specified by the guidelines, but I am not sure if those guidelines are finalized and ready to go, or if they are still in development.

For me the main driver would be to be able to determine which sessions are currently running, with the side effect of being able to delete them. This means that a delete-all endpoint feels more like a stop gap solution then a real one.

@jlurien
Copy link
Collaborator

jlurien commented Jan 25, 2023

A GET /sessions endpoint makes all sense to me. We can elaborate on the paging and/or filtering parameters. Guidelines are a start point but probably the first API needing them will lead the way.

This new endpoint add new requirements on implementations as sessions have to be associated to an owner in order to only provide "their" sessions, that is the 2-legged client_id or 3-legged user_id. So far the concept of ownership is not mentioned explicitly, and relying on the knowledge of a non guessable session_id could have served for short term. But for this new endpoint I think we should address it.

@hdamker hdamker added enhancement New feature or request QoD labels Jan 28, 2023
@hdamker
Copy link
Collaborator

hdamker commented Feb 7, 2023

Due to the requirements this new endpoint would imply for implementations we propose to move the proposal into the backlog. Also as this endpoint would be only relevant in dev/lab/test ... the main issue can be circumvented with setting a (short) duration for the QoS session.

@mariobodemann
Copy link
Contributor Author

Thanks for the update.

Would implementing the alternative A be an option as a compromise?

https://github.com/dt-developers/QualityOnDemand/blob/9f34da6fef175bf774bb9ea7d835707b36255906/code/API_definitions/qod-api.yaml#L303

@hdamker
Copy link
Collaborator

hdamker commented Feb 9, 2023

Would implementing the alternative A be an option as a compromise?

My view: Setting the default value for duration to a low value can e.g. be done locally in lab/test environments. And developers can always set it in their session create calls if they like. If we set it in general to a low value we are essentially make the parameter mandatory, at least before we have a /put or /patch method (#47). Therefore I'm not in favor of a short default duration to circumvent these issue in dev/test/lab.

But open for other thoughts on it.

@jlurien
Copy link
Collaborator

jlurien commented Oct 6, 2023

Hi, I have received recently some internal feedback to work on this functionality, to allow customers to "look for" active sessions in scenarios where sessionId is not known. I think that this functionality makes all sense in a CRUD model, but as mention before we must elaborate well the requirements around which sessions are allowed to be discovered by certain client, which filters may apply to that query, e.g. searching for sessions for certain MSISDN, etc.

TEF can work on a more detailed proposal for this

@RandyLevensalor
Copy link
Collaborator

Could we add parameters to filter this to include different session status? Do we have a list of session statuses? Active, completed, failed?

@eric-murray
Copy link
Collaborator

eric-murray commented Oct 20, 2023

I don't think a GET /sessions that returns the details of all sessions works. Those details include personal information for each device (e.g. phoneNumber), so how would this work for three-legged authentication? Are you proposing the API consumer puts the full list of device identifiers they are managing sessions for in the login_hint? That could be a very long list, would take a very long time to process, and may well exceed maximum URL length.

We already have a GET /sessions/{sessionId}, so all we need is a GET /sessions that return the list of sessionIds, and nothing else. No personal information there. Each session can then be queried individually using GET /sessions/{sessionId} until you find the one you want.

I thought that was the RESTful way to do it anyway.

@jlurien
Copy link
Collaborator

jlurien commented Oct 23, 2023

What @eric-murray mentions is something we have to define properly. In any case, the requester must have access rights to the requested information. That means that the access token must be checked in order to identify which specific sessions are associated to it. Even if we only returned sessionIds, we cannot return those corresponding to sessions not created by the requester.

In case of three-legged authentication the check must include also that sessions belong to the user identified by the token. So functionality must always be: "Get me the sessions I'm allowed to discover with this access token".

@eric-murray
Copy link
Collaborator

That means that the access token must be checked in order to identify which specific sessions are associated to it. Even if we only returned sessionIds, we cannot return those corresponding to sessions not created by the requester.

I'm concerned that you are saying all that matters for this use case is which API consumer (identified by client_id for both 2- and 3-legged tokens) created the sessions and not the consent of the end user (identified by sub in the associated id_token for a 3-legged token but not identified at all for a 2-legged token) whose personal information may be in the session information.

Whatever logic is used to implement the GET /sessions endpoint, it must only return sessions created by the client identified by the token, and that could be either a 2- or 3-legged token for this purpose. But are you saying that, if a session already exists, then end user consent does not need to be re-checked even if user resource (in this case, the device fields) is involved? The API consumer cannot consent to this, because this personal information is not theirs.

If that is the case, a 2-legged token is then fine for session retrieval and the Identity & Consent technical ruleset is wrong. But if 3-legged authorisation is required, what does the API consumer (client_id) specify as the login_hint to allow consent checking to be completed during the /bc-authorize step?

@jlurien
Copy link
Collaborator

jlurien commented Oct 24, 2023

I'm not meaning at all that client_id is the only part of the access token to be checked. For sure, consent has to be checked for 3-legged scenarios which require it. The consent would be check before an access token with scope qod-session-read is granted for the client and the user.

My point was that returning only sessionId, if we have an endpoint to get the additional details from that sessionId, does not change the situation regarding privacy.

@SyeddR
Copy link
Collaborator

SyeddR commented Nov 9, 2023

@jlurien How do you handle a situation where a client have created 100s or more sessions? Would you list them all in one GET /sessions? This could make an endpoint susceptible to heavy read request, or possible denial of service attack if not implemented correctly.

@jlurien
Copy link
Collaborator

jlurien commented Nov 10, 2023

@jlurien How do you handle a situation where a client have created 100s or more sessions? Would you list them all in one GET /sessions? This could make an endpoint susceptible to heavy read request, or possible denial of service attack if not implemented correctly.

This is related to which type of token we use. I agree that with 2-legged tokens, a client_id may own hundreds of sessions. An alternative to paging would be to add filters by device, but I'm not against considering paging for these scenarios.

For 3-legged tokens. it may not be that necessary as an individual user will likely not have hundreds of sessions.

The ultimate question is which kind of tokens are we going to use here. This is connected to the ongoing discussions in Identity and Consent Management WG. The general guideline is that "Every time personal user data is processed by an API and the user can exercise their rights either via opt-in and/or opt-out, 3-legged access tokens must be used.".

For the API definition, we could consider paging in any case, as it is optional, but it is more important to define the rules about which sessions are to be returned.

@hdamker
Copy link
Collaborator

hdamker commented Nov 20, 2023

From the discussions on the QoD Call on Friday:

The PR is stil (optional) considered for v0.10.0. Potentially the discussions can be not be closed for v0.10.0, in this case the feature will be postponed to the next release.

Discussions which are open:

  1. Can the endpoint deliver (A) all sessions created by the requesting API consumer or (B) only the ones for the user resource within the (3-legged) token? (in other word: does the endpoint later require 2-legged or 3-legged token, in case 3-legged token will (later) be required to create a QoD session resource)

    • For now the assumption is that the operation delivers all sessions which are authorized by the token (all sessions created for 2-legged, only user sessions for 3-legged). Decision about needed token is postponed.
  2. Should the operation deliver the full session information or just the session ids?

    • Result of the discussion: return the full session information
    • Rational: this is the more developer friendly option, as otherwise the API consumer would need to call getSession one by one to find the information they are looking for. From privacy perspective has the API consumer provided and seen all personal information already during the respective session creations. It should be enough that the API consumer was authorized to create the sessionId(s) to assume consent for the get operation.
  3. Is paging needed or not?

    • That depends on the answer to point 1. If only the sessions for one user device are delivered is no paging necessary. If all sessions for an API consumer are delivered then paging might be needed to avoid excessive data within the response
  4. Filtering by device or phoneNumber (Added after the call, comment from Randy Add GET /sessions endpoint for retrieving all active sessions of authenticated user #228 (comment))

    • Is it possible to filter with a complex object?

@RandyLevensalor @jlurien @eric-murray ... please add your thoughts on the points.

@patrice-conil
Copy link
Collaborator

From the discussions on the QoD Call on Friday:

The PR is stil (optional) considered for v0.10.0. Potentially the discussions can be not be closed for v0.10.0, in this case the feature will be postponed to the next release.

Discussions which are open:

  1. Can the endpoint deliver (A) all sessions created by the requesting API consumer or (B) only the ones for the user resource within the (3-legged) token? (in other word: does the endpoint later require 2-legged or 3-legged token, in case 3-legged token will (later) be required to create a QoD session resource)

    • For now the assumption is that the operation delivers all sessions which are authorized by the token (all sessions created for 2-legged, only user sessions for 3-legged). Decision about needed token is postponed.
      Totally agree on all sessions created for 2-legged, only user sessions for 3-legged
  1. Should the operation deliver the full session information or just the session ids?

    • Result of the discussion: return the full session information
    • Rational: this is the more developer friendly option, as otherwise the API consumer would need to call getSession one by one to find the information they are looking for. From privacy perspective has the API consumer provided and seen all personal information already during the respective session creations. It should be enough that the API consumer was authorized to create the sessionId(s) to assume consent for the get operation.
      I prefer "Return the full session information" that is more user friendly
  1. Is paging needed or not?

    • That depends on the answer to point 1. If only the sessions for one user device are delivered is no paging necessary. If all sessions for an API consumer are delivered then paging might be needed to avoid excessive data within the response
      No need to paginate for "single device" in 3 legs, so if we plan to migrate to 3 legs, no need to paginate at all
  1. Filtering by device or phoneNumber (Added after the call, comment from Randy Add GET /sessions endpoint for retrieving all active sessions of authenticated user #228 (comment))

    • Is it possible to filter with a complex object?
      I will prefer to define ipv4Address, ipv6Address,... as filter criteria, because is more simple.

@RandyLevensalor @jlurien @eric-murray ... please add your thoughts on the points.

@hdamker
Copy link
Collaborator

hdamker commented Nov 24, 2023

Thanks @patrice-conil for your comments on the four points ... I agree with all of them.

@RandyLevensalor @jlurien @eric-murray I would like to get your opinion if we can go today with the PR #228 as is, which means:

  1. Change of security schema will not impact the endpoint definition, as it will implicitly will deliver only the sessions allowed by the token
  2. Returning full session information as agreed
  3. No pagination for now as it don't seem to be necessary
  4. Only phoneNumber as filter parameter. It is possible to add further filter parameters in next version, that's no breaking change. But ipv4address would need some discussion, as not enough to identify a device.

Let me know if
a) you would merge the PR as is into v0.10.0 or
b) see the need to continue the discussion first and postpone the PR to next release

If there are no approvals for the PR until end of day, I'm going for b) to get the rc v0.10.0 done.

@RandyLevensalor
Copy link
Collaborator

Only phoneNumber as filter parameter. It is possible to add further filter parameters in next version, that's no breaking change. But ipv4address would need some discussion, as not enough to identify a device.

I'm not a fan to only support mobile networks. Especially when we have discussed wireline networks supporting more concurrent sessions. Why can't we we search on for a match on the device schema that's used to create the session and further refine it in a larger pr, if needed?

@hdamker
Copy link
Collaborator

hdamker commented Nov 27, 2023

@RandyLevensalor

Why can't we we search on for a match on the device schema that's used to create the session and further refine it in a larger pr, if needed?

We couldn't simply filter by whole device object - it would require changing the method from GET to POST and delivering the request body as a device object parameters to filter. Instead I'm here with @jlurien:

Is it possible to filter with a complex object?

I will prefer to define ipv4Address, ipv6Address,... as filter criteria, because is more simple.

And that can be done step by step in later releases, in line with any redefinition of device which will come.

@jlurien
Copy link
Collaborator

jlurien commented Nov 27, 2023

Only phoneNumber as filter parameter. It is possible to add further filter parameters in next version, that's no breaking change. But ipv4address would need some discussion, as not enough to identify a device.

I'm not a fan to only support mobile networks. Especially when we have discussed wireline networks supporting more concurrent sessions. Why can't we we search on for a match on the device schema that's used to create the session and further refine it in a larger pr, if needed?

This is something that we should clarify at WG level, The scope of the subproject as stated in the README says:

It provides the customer with the ability to:
set quality for a mobile connection (e.g. required latency, jitter, bit rate)
get notification if network cannot fulfill
NOTE: The scope of this API family should be limited (at least at a first stage) to 4G and 5G.

There is also another subproject dedicated to Home Devices QoD, which target home networks.

@eric-murray
Copy link
Collaborator

From the API Design Guidelines:

In such cases, it is recommended to use one of the following methods to transfer the sensitive data:

  • When using GET, transfer the data using headers, which are not routinely logged or cached
  • Use POST instead of GET, with the sensitive data being embedded in the request body which, again, is not routinely logged or cached

So MSISDN should not be passed as a query parameter, and certainly that is not allowed by Vodafone's own API security rules.

Filtering by MSISDN (or, indeed, any device identifier) needs to be achieved using a 3-legged access token. Indeed, the CAMARA APIs Access and User Consent Management Guidelines say that a 3-legged access token should ALWAYS be used for such endpoints, though I agree this is unworkable when the API is processing personal data for multiple end users.

So the phoneNumber query parameter needs to be removed before I can approve this.

On the other points:

  • I don't think this endpoint can be called using a 2-legged token (given the current user consent guidelines), but this has no effect on the YAML, so we can park that discussion for now
  • I still don't understand the argument that calling GET /sessions/{sessionId} multiple times to get the session details is more effort for the API developer, as these APIs will all be called programmatically. Who is expecting to be sat in front of a terminal typing these API calls? But if the consensus view is that all session details are returned, then I can agree to that because it just means that the API implementor has to call GET /sessions/{sessionId} multiple times instead (even if I still don't understand how you can get details for multiple end users with a 3-legged token).
  • Paging (and indeed filtering) greatly increases implementation complexity, so my preference is also not to define paging or filtering at this stage

@jlurien
Copy link
Collaborator

jlurien commented Nov 30, 2023

From the API Design Guidelines:

In such cases, it is recommended to use one of the following methods to transfer the sensitive data:

  • When using GET, transfer the data using headers, which are not routinely logged or cached
  • Use POST instead of GET, with the sensitive data being embedded in the request body which, again, is not routinely logged or cached

So MSISDN should not be passed as a query parameter, and certainly that is not allowed by Vodafone's own API security rules.

Filtering by MSISDN (or, indeed, any device identifier) needs to be achieved using a 3-legged access token. Indeed, the CAMARA APIs Access and User Consent Management Guidelines say that a 3-legged access token should ALWAYS be used for such endpoints, though I agree this is unworkable when the API is processing personal data for multiple end users.

So the phoneNumber query parameter needs to be removed before I can approve this.

On the other points:

  • I don't think this endpoint can be called using a 2-legged token (given the current user consent guidelines), but this has no effect on the YAML, so we can park that discussion for now
  • I still don't understand the argument that calling GET /sessions/{sessionId} multiple times to get the session details is more effort for the API developer, as these APIs will all be called programmatically. Who is expecting to be sat in front of a terminal typing these API calls? But if the consensus view is that all session details are returned, then I can agree to that because it just means that the API implementor has to call GET /sessions/{sessionId} multiple times instead (even if I still don't understand how you can get details for multiple end users with a 3-legged token).
  • Paging (and indeed filtering) greatly increases implementation complexity, so my preference is also not to define paging or filtering at this stage

I agree with your points. However, for GET /sessions I still think that returning the list of sessions with all data is more useful than returning just the list of Ids. Probably, in a 3-legged scenario it will be typical to have just one session.

In summary, if we go for complex filters, I would suggest a POST operation to list or search for sessions, returning a list of matched sessions info.

@RandyLevensalor
Copy link
Collaborator

Only phoneNumber as filter parameter. It is possible to add further filter parameters in next version, that's no breaking change. But ipv4address would need some discussion, as not enough to identify a device.

I'm not a fan to only support mobile networks. Especially when we have discussed wireline networks supporting more concurrent sessions. Why can't we we search on for a match on the device schema that's used to create the session and further refine it in a larger pr, if needed?

This is something that we should clarify at WG level, The scope of the subproject as stated in the README says:

It provides the customer with the ability to:
set quality for a mobile connection (e.g. required latency, jitter, bit rate)
get notification if network cannot fulfill
NOTE: The scope of this API family should be limited (at least at a first stage) to 4G and 5G.

@jlurien We should fix this. This is the first time that I've seen any pushback in any working group to supping wireline networks.

This was added to commonalities to avoid being telco specific.
https://github.com/camaraproject/Commonalities/blob/main/documentation/API-design-guidelines.md#25-reduce-telco-specific-terminology-in-api-definitions

There is also another subproject dedicated to Home Devices QoD, which target home networks.

But this can be a home network behind a FWA network and I think that is where most of the use cases are coming from, not home devices connected to wireline network.

@patrice-conil
Copy link
Collaborator

* I still don't understand the argument that calling `GET /sessions/{sessionId}` multiple times to get the session details is more effort for the API developer, as these APIs will all be called programmatically. Who is expecting to be sat in front of a terminal typing these API calls? But if the consensus view is that all session details are returned, then I can agree to that because it just means that the API implementor has to call `GET /sessions/{sessionId}` multiple times instead (even if I still don't understand how you can get details for multiple end users with a 3-legged token).

If you have to call GET /sessions/{sessionId} multiple times, you have to call them in parallel otherwise you will multiply response times... and believe me, it's not always easy... much more complex than reading a list, especially to handle errors/timeouts

@eric-murray
Copy link
Collaborator

@patrice-conil
And how long do you think it will take to get a 3-legged token valid for all possible end users whose session details might be returned by GET /sessions? The response list will include a device identifier (i.e. end user identifier) for each entry, and according to CAMARA-API-access-and-user-consent.md:

[Client credentials] can only be used when no personal user data is processed

So 3-legged token it is.

@patrice-conil
Copy link
Collaborator

Hi @eric-murray,
On my side, the session belongs to the client_id who created it... and will only be returned to this client_id.
This is how I solved the isolation issue...whether I am called by GET /sessions or GET /sessions/{sessionId} I will check if the session was created by the caller.
My comment only concerns the complexity of one request versus multiple requests.
And in fact if you get a 3-legged token valid for all users... you can call GET /sessions/{sessionId} as many times as necessary to retrieve the same information, right?
Of course, in all cases, to manage personal data, I prefer a 3-legged one.

@eric-murray
Copy link
Collaborator

@patrice-conil

On my side, the session belongs to the client_id who created it... and will only be returned to this client_id.

Yes, I agree, but the session information still contains personal data (IP address or phone number), and returning those details is "processing". So the token still needs to be associated with all the end users for which the API consumer has active sessions. That may just be one, or it may be many, or it may be very very many.

Thing is, when the session is created, the API consumer will have a 3-legged token valid for the resulting sessionId (this assumes that a wild card scope has been requested). So they will not need another token to call the GET /sessions/{sessionId} endpoint - the one they have is fine so long as they remember which sessionId it is associated with.

But if they need a 3-legged token valid for multiple end users, well, they need to request that specifically.

Ignoring the complexity of getting a valid token for now, if the list is long, then it will need to be paginated. So that will increase complexity whereas the GET /sessions/{sessionId} response will not need to be paginated.

So my feeling is that, if one single list of session details is required, then we should mandate filtering by end user identifier. That way, we get a shorter list, and can use a "normal" 3-legged token for that end user, which the API consumer will already have. This could still be GET /sessions, but with the end user identified from the token. Should such a thing as "multi-user" 3-legged tokens exist, these should be rejected.

But my preference remains that GET /sessions returns only a list of sessionIds. Client credentials can be used for that endpoint.

@patrice-conil
Copy link
Collaborator

@patrice-conil

On my side, the session belongs to the client_id who created it... and will only be returned to this client_id.

Yes, I agree, but the session information still contains personal data (IP address or phone number), and returning those details is "processing". So the token still needs to be associated with all the end users for which the API consumer has active sessions. That may just be one, or it may be many, or it may be very very many.

These personal data are already known to the client_id who provided them when creating the session... so no problem for me.
The real difficulty is returning only valid data for the token used to create sessions (the same one used in your approach to call GET /sessions/{sessionId}. Filtering by end user is therefore implicit in case of 3 legs, because the end user is involved in obtaining the token.
WDYT?

Thing is, when the session is created, the API consumer will have a 3-legged token valid for the resulting sessionId (this assumes that a wild card scope has been requested). So they will not need another token to call the GET /sessions/{sessionId} endpoint - the one they have is fine so long as they remember which sessionId it is associated with.

But if they need a 3-legged token valid for multiple end users, well, they need to request that specifically.

It's not my idea ... they will use the same token for create and list operations.

Ignoring the complexity of getting a valid token for now, if the list is long, then it will need to be paginated. So that will increase complexity whereas the GET /sessions/{sessionId} response will not need to be paginated.

So my feeling is that, if one single list of session details is required, then we should mandate filtering by end user identifier. That way, we get a shorter list, and can use a "normal" 3-legged token for that end user, which the API consumer will already have. This could still be GET /sessions, but with the end user identified from the token. Should such a thing as "multi-user" 3-legged tokens exist, these should be rejected.

Totally agree with you.

But my preference remains that GET /sessions returns only a list of sessionIds. Client credentials can be used for that endpoint.
In this case, won't the consumer have to use 2 different security schemes to call POST /sessions and GET /sessions ?

@eric-murray
Copy link
Collaborator

... they will use the same token for create and list operations.

OK, I can live with that. A GET /sessions endpoint that returns full session details, but can only be accessed using a token that was already used for POST /sessions (so only associated with a single end user). In that way, the GET /sessions list would only be for the end user associated with the token.

In this case, won't the consumer have to use 2 different security schemes to call POST /sessions and GET /sessions ?

Both could be used. 2-legged token for GET /sessions would return a list of all sessionIds created by the API consumer. 3-legged token would filter that list to only those for the end user associated with the token (but still only return list of sessionIds). Implementation complexity would increase, of course.

@jlurien
Copy link
Collaborator

jlurien commented Jan 24, 2024

This is long thread but summarizing the open points, I think we should decide on:

Filtering

Taking into account that we should avoid disclosing sensible data in paths and query parameters, I think we should choose a POST method for this operation, so it would be POST /sessions/retrieve. This gives us a lot of flexibility designing the filters in the request body, and we can reuse the same schemas that we use in other operations. The most obvious input parameter is probably the device, but we may decide to add other properties of the SessionInfo model, such as appicationServer, qosPropfile`...

We have to device if device is always required, or some minProperties are required, or even if an empty body would be allowed indicating no filters.

security & securitySchemes for the operation

Designing the operation as a POST simplifies a lot this point, as this new operation would be conceptually similar to the operation for session creation regarding security. Same considerations should apply to both. A client allowed to create a session for certain device should be allowed as well to retrieve the session info for that device. In 3-legged tokens are required for that, same token would be required to get the session data.

In case that we allow a retrieveSession operation without filters, we should rely only on the access token content to decide which sessions are authorized by the access token. In case of 3-legged tokens, this implies looking into the sub identifying the user and likely into any other identifiers for the specific device or subscription of the user.

response body

Here I would return an array of SessionInfo, again similar to the createSession operation but allowing several items to be returned, as a device may have several sessions.

I think paging will not be necessary for 3-legged scenarios.

Draft proposal

So in summary, I would propose an operation that could be drafted as:

paths:
  /sessions/retrieve:
    post:
      description: Retrieves session(s) that match the input in the body. 
      operationId: retrieveSessions
      requestBody:
        content:
          application/json:
            $ref; "#/components/schemas/RetrieveSessions"
      responses:
        "200":
          content:
           application/json:
              schema:
                type: array
              items:
                $ref: "#/components/schemas/SessionInfo"
      security:
        - oAuth2ClientCredentials: []
        - threeLegged:
            - "qod-sessions-read"
  • security should be the same that we have for the getSession operation. I copy what we have right now but we have to align security schemes to the Commonalities guidelines regarding the use of OpenID Connect
  • We have to decide on the schema for RetrieveSessions regarding the allowed filters, and whether requestBody is required or an empty object {} is allowed.

@eric-murray
Copy link
Collaborator

@jlurien

I don't think a POST is necessary in this case because:

  • The only "sensitive" parameter that could be used as a filter is device, and that MUST be known from the OAuth token, so should not be a filter parameter
  • The only "complex" object that we could consider filtering by is PortsSpec, and I just don't see that as useful

Regarding identifying the device from the OAuth token:

  • The OAuth token MUST identify one (and only one) "device" (i.e. end user). So filtering by device is automatic. There is no way to retrieve a list of sessions for all end users with the current Identity & Consent framework. The device parameter will still be included in the response of course (if only to confirm that the API consumer has used the correct token).
  • I believe POST /sessions will also eventually have to be revised, with device removed. Allowing this to be specified in the service API call can only potentially create additional error cases - either it will agree with the token (in which case, it is not required) or it will disagree (in which case it must either be ignored or an error returned). So allowing it to be specified in the service API call just complicates implementation.
  • The current problem is that the Identity & Consent working group have not yet specified a method of specifying a Network Access Identifier or IP address pair when requesting a token. But that problem can be easily solved when brought to their attention.

Filtering by parameters other than device, devicePorts or applicationServerPorts is straightforward using query parameters, e.g.:
GET /sessions?applicationServer.ipv6Address=2001:db8:85a3:8d3:1319:8a2e:370:7344

As the list must be filtered by end user (i.e. device), and hence will be short, I don't see the need for pagination.

@jlurien
Copy link
Collaborator

jlurien commented Jan 25, 2024

@eric-murray

To me the decision for GET vs POST is the result of deciding on the filters to apply for the method. I agree with you that without device there a GET is a valid option. My proposal was for the sake of coherence with the other operations we have right now, particularly createSession. So the real debate for evolution would be whether device has to be an input (required, optional or non-existent) for some operation or we should rely always on the device identified by the token.

@hdamker
Copy link
Collaborator

hdamker commented Jan 25, 2024

@eric-murray @jlurien The agreed text within CAMARA-API-access-and-user-consent.md which we will have to include also in our API specification (after it is released):

CAMARA guidelines defines a set of authorization flows which can grant API clients access to the API functionality, as outlined in the document CAMARA-API-access-and-user-consent.md. Which specific authorization flows are to be used will be determined during onboarding process, happening between the API Client and the Telco Operator exposing the API, taking into account the declared purpose for accessing the API, while also being subject to the prevailing legal framework dictated by local legislation.

It is important to remark that in cases where personal user data is processed by the API, and users can exercise their rights through mechanisms such as opt-in and/or opt-out, the use of 3-legged access tokens becomes mandatory. This measure ensures that the API remains in strict compliance with user privacy preferences and regulatory obligations, upholding the principles of transparency and user-centric data control.

That does not exclude that the QoD API can be used with Client Credentials. Even if most local legislations would require 3-legged for all purposes, there would be still deployment scenarios where the QoD API will be used with Client Credentials (e.g. in lab deployments or private networks). Therefore we can't get completely rid of the device parameter but should keep it at least optional.

But as @jlurien rightly recognized, that is going beyond this issue.

@jlurien
Copy link
Collaborator

jlurien commented Jan 26, 2024

With @hdamker remarks, I tend to think that probably the most safe approach is to consider device as an optional input parameter for both retrieveSessions and createSession, in which case I would model both in a similar way with a POST method.

Apart from the hypothetical 2-legged possibility in some environment or geography, there is also a possible 3-legged scenario where a token is granted for a user (sub) which may have several lines, for example using user/pass credentials, and in that case it may be necessary to indicate which of the user devices is requested.

@eric-murray
Copy link
Collaborator

@jlurien @hdamker
I agree that if we want to keep device as an optional input parameter, then we need to use POST. I'd also add a comment that this field will be ignored if a device can be identified from the token so that the behaviour is clear.

I'm not convinced that multi-user tokens are feasible - it already takes too long to generate and process a token for one end user. But that is indeed not a topic for this issue.

@hdamker hdamker added the v0.11.0 Within scope for v0.11.0 label Feb 11, 2024
@jlurien
Copy link
Collaborator

jlurien commented Mar 22, 2024

To propose a PR we should have some prior consensus on how to model the endpoint. The options I see:

a) GET /sessions -> No explicit input parameters. All input has to be taken from the access token

b) POST /sessions/retrieve { device required } -> Similar behaviour of current createSessions

c) POST /sessions/retrieve { device optional } -> If device is included, similar behaviour of current createSessions. If device is not included, all input has to be taken from the access token.

The implications can be extended to the current endpoints. There are some questions that are not yet resolved:

  • When creating a session, the implementation should check the coherence between the required device and the access token. For 3-legged scenarios device should be redundant, so it would make sense to make device optional as well for createSessions.

  • Ownership of a session, When getting or deleting a session by sessionId, should the implementation validate that session was created by the same client_id? Now we somehow rely on sessionId as being a secret, but this is not very consistent.

    • If a user gives consent to a client_id to manage their sessions, would that imply giving permission to get to delete a session created by other client_id or not?

@jlurien
Copy link
Collaborator

jlurien commented May 30, 2024

To proceed with this functionality, which is in the backlog for v0.11, I propose to align the new endpoint as much as possible to the current consensus in v0.10.

That would imply modelling the endpoint as option B above (POST /sessions/retrieve { device required } ). In parallel, there is an ongoing discussion in camaraproject/Commonalities#171 to consider the input device as optional, and rely on the access token when is possible (which would be the option C above). If there is a final decision in Commonalities to make device optional, then we would have to align both the current createSession and the new retrieveSessions.

If this is OK, I can model a PR with the proposal.

@RandyLevensalor
Copy link
Collaborator

My concern is that I don't see anything that would limit the three-legged token to just on device, but a set of devices. While I can see expanding this to retrieve all sessions associated within the scope of the token, I think that we'll still need to support the device id. Added this comment to the commonalities issue as well. camaraproject/Commonalities#171 (comment)

For the device ID, what about embedding the json from the #/components/schemas/Device schema in the requestbody. Then if we need to update the Device schema to comply with commonalities, we'll only have to do it in the QoD schema.

@jlurien
Copy link
Collaborator

jlurien commented May 31, 2024

The debate is in Commonalities, but there are many cases where a 3-legged token will identify a single device, such as in a network-based auth flow launched from the device. In any case, this will not be a universal case and device has to be supported anyway, optional or required.

The proposal is exactly that, to reuse the same device schema in the request body, modeling an operation POST /sessions/retrieve { device }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request QoD v0.11.0 Within scope for v0.11.0
Projects
None yet
7 participants