chore: upgrade to v3 guide
first version with sed scripts.
This commit is contained in:
parent
434b2e62d8
commit
49f252f37e
1 changed files with 340 additions and 0 deletions
340
UPGRADING.md
Normal file
340
UPGRADING.md
Normal file
|
@ -0,0 +1,340 @@
|
|||
# Upgrading
|
||||
|
||||
All commands are executed from the root of the project that imports oidc packages.
|
||||
`sed` commands are created with GNU `sed` in mind and might need alternate syntax
|
||||
on non-GNU systems, such as MacOS or the GNU sed command to be installed manually.
|
||||
|
||||
## V2 to V3
|
||||
|
||||
As first steps we will:
|
||||
1. Download the latest v3 module;
|
||||
2. Replace imports in all Go files;
|
||||
3. Tidy the module file;
|
||||
|
||||
```bash
|
||||
go get -u github.com/zitadel/oidc/v3
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/github\.com\/zitadel\/oidc\/v2/github.com\/zitadel\/oidc\/v3/g'
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
### global
|
||||
|
||||
#### go-jose package
|
||||
|
||||
`gopkg.in/square/go-jose.v2` import has been changed to `github.com/go-jose/go-jose/v3`.
|
||||
That means that the imported types are also changed and imports need to be adapted.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/gopkg.in\/square\/go-jose\.v2/github.com\/go-jose\/go-jose\/v3/g'
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
### op
|
||||
|
||||
```go
|
||||
import "github.com/zitadel/oidc/v3/pkg/op"
|
||||
```
|
||||
|
||||
#### Logger
|
||||
|
||||
RequestError...
|
||||
AuthRequestError...
|
||||
|
||||
TODO
|
||||
|
||||
#### AccessTokenVerifier
|
||||
|
||||
`AccessTokenVerifier` interface has become a struct type. `NewAccessTokenVerifier` now returns a pointer to `AccessTokenVerifier`.
|
||||
Variable and struct fields declarations need to be changed from `op.AccessTokenVerifier` to `*op.AccessTokenVerifier`.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/\bop\.AccessTokenVerifier\b/*op.AccessTokenVerifier/g'
|
||||
```
|
||||
|
||||
#### JWTProfileVerifier
|
||||
|
||||
`JWTProfileVerifier` interface has become a struct type. `NewJWTProfileVerifier` now returns a pointer to `JWTProfileVerifier`.
|
||||
Variable and struct fields declarations need to be changed from `op.JWTProfileVerifier` to `*op.JWTProfileVerifier`.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/\bop\.JWTProfileVerifier\b/*op.JWTProfileVerifier/g'
|
||||
```
|
||||
|
||||
#### IDTokenHintVerifier
|
||||
|
||||
`IDTokenHintVerifier` interface has become a struct type. `NewIDTokenHintVerifier` now returns a pointer to `IDTokenHintVerifier`.
|
||||
Variable and struct fields declarations need to be changed from `op.IDTokenHintVerifier` to `*op.IDTokenHintVerifier`.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/\bop\.IDTokenHintVerifier\b/*op.IDTokenHintVerifier/g'
|
||||
```
|
||||
|
||||
#### ParseRequestObject
|
||||
|
||||
`ParseRequestObject` no longer returns `*oidc.AuthRequest` as it already operates on the pointer for the passed `authReq` argument. As such the argument and the return value were the same pointer. Callers can just use the original `*oidc.AuthRequest` now.
|
||||
|
||||
#### Endpoint Configuration
|
||||
|
||||
`Endpoint`s returned from `Configuration` interface methods are now pointers. Usually, `op.Provider` is the main implementation of the `Configuration` interface. However, if a custom implementation is used, you should be able to update it using the following:
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/AuthorizationEndpoint() Endpoint/AuthorizationEndpoint() *Endpoint/g' \
|
||||
-e 's/TokenEndpoint() Endpoint/TokenEndpoint() *Endpoint/g' \
|
||||
-e 's/IntrospectionEndpoint() Endpoint/IntrospectionEndpoint() *Endpoint/g' \
|
||||
-e 's/UserinfoEndpoint() Endpoint/UserinfoEndpoint() *Endpoint/g' \
|
||||
-e 's/RevocationEndpoint() Endpoint/RevocationEndpoint() *Endpoint/g' \
|
||||
-e 's/EndSessionEndpoint() Endpoint/EndSessionEndpoint() *Endpoint/g' \
|
||||
-e 's/KeysEndpoint() Endpoint/KeysEndpoint() *Endpoint/g' \
|
||||
-e 's/DeviceAuthorizationEndpoint() Endpoint/DeviceAuthorizationEndpoint() *Endpoint/g'
|
||||
```
|
||||
|
||||
#### CreateDiscoveryConfig
|
||||
|
||||
`CreateDiscoveryConfig` now takes a context as first argument. The following adds `context.TODO()` to the function:
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/op\.CreateDiscoveryConfig(/op.CreateDiscoveryConfig(context.TODO(), /g'
|
||||
```
|
||||
|
||||
#### CreateRouter
|
||||
|
||||
`CreateRouter` now returns a `chi.Router` instead of `*mux.Router`.
|
||||
Usually this function is called when the Provider is constructed and not by package consumers.
|
||||
However if your project does call this function directly, manual update of the code is required.
|
||||
|
||||
#### DeviceAuthorizationStorage
|
||||
|
||||
`DeviceAuthorizationStorage` dropped the following methods:
|
||||
|
||||
- `GetDeviceAuthorizationByUserCode`
|
||||
- `CompleteDeviceAuthorization`
|
||||
- `DenyDeviceAuthorization`
|
||||
|
||||
These methods proved not to be required from a library point of view.
|
||||
Implementations of a device authorization flow may take care of these calls in a way they see fit.
|
||||
|
||||
#### AuthorizeCodeChallenge
|
||||
|
||||
The `AuthorizeCodeChallenge` function now only takes the `CodeVerifier` argument, instead of the complete `*oidc.AccessTokenRequest`.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/op\.AuthorizeCodeChallenge(tokenReq/op.AuthorizeCodeChallenge(tokenReq.CodeVerifier/g'
|
||||
```
|
||||
|
||||
### client
|
||||
|
||||
```go
|
||||
import "github.com/zitadel/oidc/v3/pkg/client"
|
||||
```
|
||||
|
||||
#### Context
|
||||
|
||||
All client calls now take a context as first argument. The following adds `context.TODO()` to all the affected functions:
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/client\.Discover(/client.Discover(context.TODO(), /g' \
|
||||
-e 's/client\.CallTokenEndpoint(/client.CallTokenEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallEndSessionEndpoint(/client.CallEndSessionEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallRevokeEndpoint(/client.CallRevokeEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallTokenExchangeEndpoint(/client.CallTokenExchangeEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallDeviceAuthorizationEndpoint(/client.CallDeviceAuthorizationEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.JWTProfileExchange(/client.JWTProfileExchange(context.TODO(), /g'
|
||||
```
|
||||
|
||||
#### keyFile type
|
||||
|
||||
The `keyFile` struct type is now exported a `KeyFile` and returned by the `ConfigFromKeyFile` and `ConfigFromKeyFileData`. No changes are needed on the caller's side.
|
||||
|
||||
### client/profile
|
||||
|
||||
The package now defines a new interface `TokenSource` which compliments the `oauth2.TokenSource` with a `TokenCtx` method, so that a context can be explicitly added on each call. Users can migrate to the new method when they whish.
|
||||
|
||||
`NewJWTProfileTokenSource` now takes a context as first argument, so do the related `NewJWTProfileTokenSourceFromKeyFile` and `NewJWTProfileTokenSourceFromKeyFileData`. The context is used for the Discovery request.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/profile\.NewJWTProfileTokenSource(/profile.NewJWTProfileTokenSource(context.TODO(), /g' \
|
||||
-e 's/profile\.NewJWTProfileTokenSourceFromKeyFileData(/profile.NewJWTProfileTokenSourceFromKeyFileData(context.TODO(), /g' \
|
||||
-e 's/profile\.NewJWTProfileTokenSourceFromKeyFile(/profile.NewJWTProfileTokenSourceFromKeyFile(context.TODO(), /g'
|
||||
```
|
||||
|
||||
|
||||
### client/rp
|
||||
|
||||
```go
|
||||
import "github.com/zitadel/oidc/v3/pkg/client/rs"
|
||||
```
|
||||
|
||||
#### Discover
|
||||
|
||||
The `Discover` function has been removed. Use `client.Discover` instead.
|
||||
|
||||
#### Context
|
||||
|
||||
Most `rp` functions now require a context as first argument. The following adds `context.TODO()` to the function that have no additional changes. Functions with more complex changes are documented below.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/rp\.NewRelyingPartyOIDC(/rp.NewRelyingPartyOIDC(context.TODO(), /g' \
|
||||
-e 's/rp\.EndSession(/rp.EndSession(context.TODO(), /g' \
|
||||
-e 's/rp\.RevokeToken(/rp.RevokeToken(context.TODO(), /g' \
|
||||
-e 's/rp\.DeviceAuthorization(/rp.DeviceAuthorization(context.TODO(), /g'
|
||||
```
|
||||
|
||||
Remember to replace `context.TODO()` with a context that is applicable for your app, where possible.
|
||||
|
||||
#### RefreshAccessToken
|
||||
|
||||
1. Renamed to `RefreshTokens`;
|
||||
2. A context must be passed;
|
||||
3. An `*oidc.Tokens` object is now returned, which included an ID Token if it was returned by the server;
|
||||
4. The function is now generic and requires a type argument for the `IDTokenClaims` implementation inside the returned `oidc.Tokens` object;
|
||||
|
||||
For most use cases `*oidc.IDTokenClaims` can be used as type argument. A custom implementation of `oidc.IDClaims` can be used if type-safe access to custom claims is required.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/rp\.RefreshAccessToken(/rp.RefreshTokens[*oidc.IDTokenClaims](context.TODO(), /g'
|
||||
```
|
||||
|
||||
Users that called `tokens.Extra("id_token").(string)` and a subsequent `VerifyTokens` to get the claims, no longer need to do this. The ID token is verified (when present) by `RefreshTokens` already.
|
||||
|
||||
|
||||
#### Userinfo
|
||||
|
||||
1. A context must be passed as first argument;
|
||||
2. The function is now generic and requires a type argument for the returned user info object;
|
||||
|
||||
For most use cases `*oidc.UserInfo` can be used a type argument. A [custom implementation](https://pkg.go.dev/github.com/zitadel/oidc/v3/pkg/client/rp#example-Userinfo-Custom) of `rp.SubjectGetter` can be used if type-safe access to custom claims is required.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/rp\.Userinfo(/rp.Userinfo[*oidc.UserInfo](context.TODO(), /g'
|
||||
```
|
||||
|
||||
#### UserinfoCallback
|
||||
|
||||
`UserinfoCallback` has an additional type argument fot the `UserInfo` object. Typically the type argument can be inferred by the compiler, by the function that is passed. The actual code update cannot be done by a simple `sed` script and depends on how the caller implemented the function.
|
||||
|
||||
|
||||
#### IDTokenVerifier
|
||||
|
||||
`IDTokenVerifier` interface has become a struct type. `NewIDTokenVerifier` now returns a pointer to `IDTokenVerifier`.
|
||||
Variable and struct fields declarations need to be changed from `rp.IDTokenVerifier` to `*rp.AccessTokenVerifier`.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/\brp\.IDTokenVerifier\b/*rp.IDTokenVerifier/g'
|
||||
```
|
||||
|
||||
### client/rs
|
||||
|
||||
```go
|
||||
import "github.com/zitadel/oidc/v3/pkg/client/rs"
|
||||
```
|
||||
|
||||
#### NewResourceServer
|
||||
|
||||
The `NewResourceServerClientCredentials` and `NewResourceServerJWTProfile` constructor functions now take a context as first argument.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/rs\.NewResourceServerClientCredentials(/rs.NewResourceServerClientCredentials(context.TODO(), /g' \
|
||||
-e 's/rs\.NewResourceServerJWTProfile(/rs.NewResourceServerJWTProfile(context.TODO(), /g'
|
||||
```
|
||||
|
||||
#### Introspect
|
||||
|
||||
`Introspect` is now generic and requires a type argument for the returned introspection response. For most use cases `*oidc.IntrospectionResponse` can be used as type argument. Any other response type if type-safe access to [custom claims](https://pkg.go.dev/github.com/zitadel/oidc/v3/pkg/client/rs#example-Introspect-Custom) is required.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/rs\.Introspect(/rs.Introspect[*oidc.IntrospectionResponse](/g'
|
||||
```
|
||||
|
||||
### client/tokenexchange
|
||||
|
||||
The `TokenExchanger` constructor functions `NewTokenExchanger` and `NewTokenExchangerClientCredentials` now take a context as first argument.
|
||||
As well as the `ExchangeToken` function.
|
||||
|
||||
```bash
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/tokenexchange\.NewTokenExchanger(/tokenexchange.NewTokenExchanger(context.TODO(), /g' \
|
||||
-e 's/tokenexchange\.NewTokenExchangerClientCredentials(/tokenexchange.NewTokenExchangerClientCredentials(context.TODO(), /g' \
|
||||
-e 's/tokenexchange\.ExchangeToken(/tokenexchange.ExchangeToken(context.TODO(), /g'
|
||||
```
|
||||
|
||||
### oidc
|
||||
|
||||
#### SpaceDelimitedArray
|
||||
|
||||
The `SpaceDelimitedArray` type's `Encode()` function has been renamed to `String()` so it implements the `fmt.Stringer` interface. If the `Encode` method was called by a package consumer, it should be changed manually.
|
||||
|
||||
#### Verifier
|
||||
|
||||
The `Verifier` interface as been changed into a struct type. The struct type is aliased in the `op` and `rp` packages for the specific token use cases. See the relevant section above.
|
||||
|
||||
### Full script
|
||||
|
||||
For the courageous this is the full `sed` script which combines all the steps described above.
|
||||
It should migrate most of the code in a repository to a more-or-less compilable state,
|
||||
using defaults such as `context.TODO()` where possible.
|
||||
|
||||
Warnings:
|
||||
- Again, this is written for **GNU sed** not the posix variant.
|
||||
- Assumes imports that use the package names, not aliases.
|
||||
- Do this on a project with version control (eg Git), that allows you to rollback if things went wrong.
|
||||
- The script has been tested on the [ZITADEL](https://github.com/zitadel/zitadel) project, but we do not use all affected symbols. Parts of the script are mere guesswork.
|
||||
|
||||
```bash
|
||||
go get -u github.com/zitadel/oidc/v3
|
||||
find . -type f -name '*.go' | xargs sed -i \
|
||||
-e 's/github\.com\/zitadel\/oidc\/v2/github.com\/zitadel\/oidc\/v3/g' \
|
||||
-e 's/gopkg.in\/square\/go-jose\.v2/github.com\/go-jose\/go-jose\/v3/g' \
|
||||
-e 's/\bop\.AccessTokenVerifier\b/*op.AccessTokenVerifier/g' \
|
||||
-e 's/\bop\.JWTProfileVerifier\b/*op.JWTProfileVerifier/g' \
|
||||
-e 's/\bop\.IDTokenHintVerifier\b/*op.IDTokenHintVerifier/g' \
|
||||
-e 's/AuthorizationEndpoint() Endpoint/AuthorizationEndpoint() *Endpoint/g' \
|
||||
-e 's/TokenEndpoint() Endpoint/TokenEndpoint() *Endpoint/g' \
|
||||
-e 's/IntrospectionEndpoint() Endpoint/IntrospectionEndpoint() *Endpoint/g' \
|
||||
-e 's/UserinfoEndpoint() Endpoint/UserinfoEndpoint() *Endpoint/g' \
|
||||
-e 's/RevocationEndpoint() Endpoint/RevocationEndpoint() *Endpoint/g' \
|
||||
-e 's/EndSessionEndpoint() Endpoint/EndSessionEndpoint() *Endpoint/g' \
|
||||
-e 's/KeysEndpoint() Endpoint/KeysEndpoint() *Endpoint/g' \
|
||||
-e 's/DeviceAuthorizationEndpoint() Endpoint/DeviceAuthorizationEndpoint() *Endpoint/g' \
|
||||
-e 's/op\.CreateDiscoveryConfig(/op.CreateDiscoveryConfig(context.TODO(), /g' \
|
||||
-e 's/op\.AuthorizeCodeChallenge(tokenReq/op.AuthorizeCodeChallenge(tokenReq.CodeVerifier/g' \
|
||||
-e 's/client\.Discover(/client.Discover(context.TODO(), /g' \
|
||||
-e 's/client\.CallTokenEndpoint(/client.CallTokenEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallEndSessionEndpoint(/client.CallEndSessionEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallRevokeEndpoint(/client.CallRevokeEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallTokenExchangeEndpoint(/client.CallTokenExchangeEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.CallDeviceAuthorizationEndpoint(/client.CallDeviceAuthorizationEndpoint(context.TODO(), /g' \
|
||||
-e 's/client\.JWTProfileExchange(/client.JWTProfileExchange(context.TODO(), /g' \
|
||||
-e 's/profile\.NewJWTProfileTokenSource(/profile.NewJWTProfileTokenSource(context.TODO(), /g' \
|
||||
-e 's/profile\.NewJWTProfileTokenSourceFromKeyFileData(/profile.NewJWTProfileTokenSourceFromKeyFileData(context.TODO(), /g' \
|
||||
-e 's/profile\.NewJWTProfileTokenSourceFromKeyFile(/profile.NewJWTProfileTokenSourceFromKeyFile(context.TODO(), /g' \
|
||||
-e 's/rp\.NewRelyingPartyOIDC(/rp.NewRelyingPartyOIDC(context.TODO(), /g' \
|
||||
-e 's/rp\.EndSession(/rp.EndSession(context.TODO(), /g' \
|
||||
-e 's/rp\.RevokeToken(/rp.RevokeToken(context.TODO(), /g' \
|
||||
-e 's/rp\.DeviceAuthorization(/rp.DeviceAuthorization(context.TODO(), /g' \
|
||||
-e 's/rp\.RefreshAccessToken(/rp.RefreshTokens[*oidc.IDTokenClaims](context.TODO(), /g' \
|
||||
-e 's/rp\.Userinfo(/rp.Userinfo[*oidc.UserInfo](context.TODO(), /g' \
|
||||
-e 's/\brp\.IDTokenVerifier\b/*rp.IDTokenVerifier/g' \
|
||||
-e 's/rs\.NewResourceServerClientCredentials(/rs.NewResourceServerClientCredentials(context.TODO(), /g' \
|
||||
-e 's/rs\.NewResourceServerJWTProfile(/rs.NewResourceServerJWTProfile(context.TODO(), /g' \
|
||||
-e 's/rs\.Introspect(/rs.Introspect[*oidc.IntrospectionResponse](/g' \
|
||||
-e 's/tokenexchange\.NewTokenExchanger(/tokenexchange.NewTokenExchanger(context.TODO(), /g' \
|
||||
-e 's/tokenexchange\.NewTokenExchangerClientCredentials(/tokenexchange.NewTokenExchangerClientCredentials(context.TODO(), /g' \
|
||||
-e 's/tokenexchange\.ExchangeToken(/tokenexchange.ExchangeToken(context.TODO(), /g'
|
||||
go mod tidy
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue