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

Implement Personal Access Tokens (PATs) #2048

Open
dborovcanin opened this issue Dec 1, 2022 · 11 comments · May be fixed by #2492
Open

Implement Personal Access Tokens (PATs) #2048

dborovcanin opened this issue Dec 1, 2022 · 11 comments · May be fixed by #2492
Assignees
Milestone

Comments

@dborovcanin
Copy link
Collaborator

dborovcanin commented Dec 1, 2022

API keys will be used for communication between services. This can be done even as a separate service, but we'll first need some investigation and specs before implementing it. @arvindh123 Please write all the findings in the comment section of this issue.

@dborovcanin dborovcanin transferred this issue from another repository Dec 29, 2023
@dborovcanin dborovcanin transferred this issue from another repository Dec 29, 2023
@dborovcanin dborovcanin transferred this issue from absmach/magistrala-old Jan 10, 2024
@dborovcanin dborovcanin moved this to Todo in SuperMQ May 9, 2024
@dborovcanin dborovcanin added this to the S4 milestone May 9, 2024
@dborovcanin
Copy link
Collaborator Author

@arvindh123 Please link here comments from the initial implementation you've done.

@dborovcanin dborovcanin moved this from Todo to In Progress in SuperMQ May 15, 2024
@dborovcanin dborovcanin modified the milestones: S4, S5 May 15, 2024
@arvindh123
Copy link
Contributor

arvindh123 commented Jun 5, 2024

API Keys which here mentioned are Personal Access Token

PAT have scopes, PAT might or might not have full access to Magistrala. A Magistrala user can create PAT with limited scopes like Example: PAT with scopes of read only things, users, domains. This PAT could not create any entities.

PAT are helps to run automation scripts without user interventions. We could not use password for automations scripts, because If authentication system have Multi-Factor authentication, then it needs human intervention, which becomes interruptions for automation scripts.

If PAT is compromised, we can simply revoke it and create new . PAT might not have full access. So with compromised PAT (PAT with limited scope) no one could not do much things like beyond the scope mentioned in PAT, Example if a compromised PAT is created with read only access, then no one could not do operations like create or delete.

@arvindh123
Copy link
Contributor

PAT Data structure

{
    "platform": {
        "users": {
            "create": {},
            "read": {},
            "list": {},
            "update": {},
            "delete": {}
        }
    },
    "domains": {
        "domain_1": {
            "entities": {
                "groups": {
                    "create": {}, // this for all groups in domain
                },
                "channels": {
                    // for particular channel in domain
                    "delete": {
                        "channel1": {},
                        "channel2":{}
                    }
                },
                "things": {
                    "update": {} // this for all things in domain
                }
            }
        }
    }
}

@arvindh123
Copy link
Contributor

arvindh123 commented Jun 17, 2024

I'm trying to explain here challenges with example use case

Lets take things share function, It requires Token for Authn and Authz.

The PAT will be passed Bearer Token via header.
The service function input variable token will either access token or PAT

Typically, for access token , grpc function Identify returns user id , domain id , subject id.
These ids are required for further process.

In auth Identify grpc call we can verify the PAT originality.
But in response we can return only user ID.
Because PAT are not specific to domain, it is specific to user.
A PAT might contains scopes for multiple domains.

So service function could not determine on which domain request need to process.
The Authorization grpc call needs domain id to do authorization.

In service function, input variable id provide the thing ID.
Using this thing ID we can find the PAT have access that thing ID and domain ID.
But down side, since we don't know the domain ID , So we need to iterating over all domains in PAT to find. This is not efficient process.

// Token - Access token / PAT encoded ID
func (svc service) Share(ctx context.Context, token, id, relation string, userids ...string) error {
	user, err := svc.identify(ctx, token) // grpc identify call
	// users = { user id , pat id } -> response for PAT,  missing domain ID
	if err != nil {
		return err
	}

	if _, err := svc.authorize(ctx, user.GetDomainId(), auth.UserType, auth.TokenKind, user.GetId(), auth.DeletePermission, auth.ThingType, id); err != nil {
		return errors.Wrap(svcerr.ErrAuthorization, err)
	}

	policies := magistrala.AddPoliciesReq{}
	for _, userid := range userids {
		policies.AddPoliciesReq = append(policies.AddPoliciesReq, &magistrala.AddPolicyReq{
			SubjectType: auth.UserType,
			Subject:     auth.EncodeDomainUserID(user.GetDomainId(), userid),
			Relation:    relation,
			ObjectType:  auth.ThingType,
			Object:      id,
		})
	}
	res, err := svc.auth.AddPolicies(ctx, &policies)
	if err != nil {
		return errors.Wrap(errAddPolicies, err)
	}
	if !res.Added {
		return err
	}
	return nil
}

Options:

  • Change endpoint from "/things/{thingid}/share" to "/domains/{domainID}/things/{thingid}/share"
    Additional Advantage: We can remove domain login, and single login is enough for all domains.
    Downside: It not give feel like multitenant application experience from API point. With this approach we can remove domain login.

  • Moving Domain ID to the end of data structure , like below example:
    DownSide: Unwanted duplication of Data, which easily makes PAT size heavier.

 "channels": {
        // for particular channel in domain
        "delete": {
                "channel1": "domain1",
                "channel2":"domain2"
          }
  },
  • Having separate PAT for domain each domain and separate Platform level operations. PAT will be created for specific domain, So PAT metadata will contain domain ID .
    In this method, In request , domain ID is not needed, On PAT identify we can return the domain ID. That can be used further by authorization.
    Downside: In approach Platform administrator / maintainers need multiple PATs for automation tasks

ToDo:

  • Check with other platforms about PAT.
  • Check with Key value store like etcd, badger

@arvindh123
Copy link
Contributor

@dborovcanin
If we add domainID to all the endpoints like /domains/{domainID}/things/{thingid}/share
Then we need to modify the addons endpoints , since they also works on domain level.
And also we need to extend PAT for Addons services. I hope with modifying auth function (make it work with PAT) we can make it work for all services including addons

@arvindh123
Copy link
Contributor

arvindh123 commented Jun 18, 2024

@arvindh123
Copy link
Contributor

@arvindh123
Copy link
Contributor

I'm leaning towards Badger, It looks promising for me.
Badger’s design is based on a paper titled WiscKey: Separating Keys from Values in SSD-conscious Storage.

And we can implement distribute Badger with Raft as mentioned in previous comment

@dborovcanin dborovcanin changed the title Work on API keys - spec and implementation needed Work on PAT - spec and implementation needed Jul 10, 2024
@dborovcanin dborovcanin modified the milestones: 0.15.0, v0.16.0 Jul 10, 2024
@dborovcanin
Copy link
Collaborator Author

We will need this for Dashboards sharing on our UI.

@dborovcanin dborovcanin moved this from 🚧 In Progress to 🛑 Blocked in SuperMQ Aug 28, 2024
@dborovcanin
Copy link
Collaborator Author

This is blocked by the new Auth model, but it is also blocking dashboards sharing on the UI side, so we must address it in this sprint.

@dborovcanin
Copy link
Collaborator Author

This ticket is becoming urgent due to plans to use PAT in Dashboard sharing and other projects that utilize MG auth services.

@dborovcanin dborovcanin changed the title Work on PAT - spec and implementation needed Implement Personal Access Tokens (PATs) Sep 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🩺 Review and testing
Development

Successfully merging a pull request may close this issue.

5 participants