OAuth 和审计日志

huangapple go评论54阅读模式
英文:

OAuth and Audit Logs

问题

在我们公司,我们有自己的Identity Server 4实现,用于发放访问令牌并授予对API的访问权限。我面临的问题是,我们目前在每个数据库实体上都有一个审计字段,形式如下:

CreatedByUserId BIGINT NOT NULL
CreatedDateTime DATETIME NOT NULL
UpdatedByUserId BIGINT NOT NULL
UpdatedDateTime DATETIME NOT NULL

直到最近这都没有问题。我们有一些数据库中间件,它会读取我们的访问令牌中的子声明,并用它来填充审计字段。但现在我们需要定期运行一个自动作业,每30分钟更新数据库。问题是,现在引发了一个问题,如果我有一些进程或通过客户端凭据流接收API调用,而在交互中没有用户存在,我该如何记录是"Service X"更新了这个实体,或者"OtherCompany.ApiClient"插入了那条记录。我可以怎么做?如何审计用户和非用户?即使需要模式更改,我也需要一些想法。

这些审计字段的主要用例是我们的应用程序中有一些页面,业务要求我们显示最后更新实体的用户和时间。显然,这些审计字段不是我们的真正事实来源,因为在数据更改时,我们在幕后进行了实际的按属性审计日志记录。

我想到的一个想法是在表中添加CreatedByUsername和UpdatedByUsername字段,然后使用访问令牌中的信息(要么是用户的用户名,要么是客户端凭据令牌的情况下客户端的显示名称)来填充这些值。这样,我们就在行级别拥有了所有的显示信息。这种方法唯一的问题是我们的护士中有很多是女性,女性在结婚时往往会改姓。所以要么他们必须根据他们的两个姓来搜索实体,要么当他们更改姓名以便在每个其他服务中追溯地更改名字时,我们必须传播一个用户名更新事件。

有什么想法吗?

英文:

At my company we have our own identity server 4 implementation that we use to issue access tokens and grant access to our API's. The problem that I'm facing is that we currently have audit field on every one of our database entities in the form of

CreatedByUserId BIGINT NOT NULL
CreatedDateTime DATETIME NOT NULL
UpdatedByUserId BIGINT NOT NULL
UpdatedDateTime DATETIME NOT NULL

Up until recently this has been fine. We have some database middleware that reads the sub claim from our access token and uses it to populate the audit fields. But we now have need to run an automated job that will update the database every 30 minutes. The problem is that this now raises the question, if I have processes or receive api calls via the client credentials flow where there is no user present in the interaction, how should I go about logging that it was "Service X" that updated this entity or "OtherCompany.ApiClient" that inserted that record. What can I do? How can I audit both users and non-users? Even if it required schema changes I am in need of ideas.

The main use case for these audit fields is that we have certain pages in our application where the business has asked that we display which user last updated an entity and when. And obviously these audit fields are not our true source of truth, as we do actual per-property audit logging behind the scenes when data changes.

One idea I had was to add a CreatedByUsername and UpdatedByUsername fields to tables, and then use information from the access token (either the user's username or the display name of the client in the case of client credentials tokens) to populate those values. That way we have all of the display information we need right there at row level. The only problem with this approach is a lot of our nurses are female, and females tend to change their name when they get married. So either they have to search for entities based on both of their last names, or we have to propogate a username updated event when they change their name to retroactively change the name in every other service.

Any ideas?

答案1

得分: 1

用户ID不应该是一个姓名。我总是尝试在访问令牌中使用不透明的主题声明,比如UUID,这样当名称发生变化时就没有影响。

在您的“领域特定数据”中,可能会有不同历史用户ID,比如数据库主键,用于表示护士,并映射到代表患者护理的资源。如果是这样,这可能是在审核记录中使用的更好的用户ID。

还要记住,个人数据,如用户名,通常受到像GDPR这样的法规的约束。一个好的做法是仅在授权服务器中存储这些字段,并仅在OAuth令牌中临时返回给应用程序级组件。我会避免冗余的名称字段。

应用程序需要显示的是供人类查看的报告。这与最佳存储格式不同。我会通过某种代码或数据库中的连接来管理这个问题。

后端作业实际上不是一个用户。一种选择可能是将审核用户保留为空,然后特殊解释它。另一个选项,可能会简化报告实现,是为后端作业创建某种伪用户记录。

英文:

A user ID should not be a name. I always try to use subject claims in access tokens that are opaque, such as a UUID. So there is no impact when names change, which they will.

In your domain specific data there may be a different historical user ID, such as a database prinary key, to represent a nurse, that is mapped to resources representing patient care. If so, this might be a better user ID to use in your audit records.

Bear in mind also that personal data such as user names is often subject to regulations like GDPR these days. A good practice is to store such fields only in the authorization server, and return them only to application level components temporarily, in OAuth tokens. I would avoid denormalized name fields.

What the application needs to display is a report for humans. This is not the same as the best storage format. I would manage that by some kind of join, either in code or a database.

The backend job is not really a user. One option might be to leave the audit user null for such updates, then interpret that specially. Another option, that might sumplify a report implementation, might be to create some kind of pseudo user record for the backend job.

答案2

得分: 0

使用UUID作为用户的唯一标识符,而不是使用用户的姓名,以避免与姓名更改相关的问题。

审计日志应主要关注用户的唯一标识符(UUID),而不是他们的个人信息。

为了在应用程序报告中显示最后更新的信息和用户详情,根据唯一用户ID(UUID)在审计日志和用户数据之间执行连接操作。

英文:

Building upon @Gary instead of using the user's name, generate and assign UUIDs as unique identifiers for users. This is can be considered primary to avoids issues related to name changes.

The audit logs should primarily focus on the user's unique identifier (UUID) rather than their personal details.

To display the last updated information and user details in the application reports, perform joins between the audit logs and the user data based on the unique user ID (UUID).

huangapple
  • 本文由 发表于 2023年5月22日 12:26:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76303029.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定