Merge branch 'main' into op
# Conflicts: # pkg/client/rp/relaying_party.go
This commit is contained in:
commit
cef977adc2
8 changed files with 95 additions and 11 deletions
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
|
@ -2,9 +2,12 @@ name: Release
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
- main
|
||||
tags-ignore:
|
||||
- '**'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
|
21
README.md
21
README.md
|
@ -21,11 +21,23 @@ Whenever possible we tried to reuse / extend existing packages like `OAuth2 for
|
|||
|
||||
Check the `/example` folder where example code for different scenarios is located.
|
||||
|
||||
```bash
|
||||
# start oidc op server
|
||||
# oidc discovery http://localhost:9998/.well-known/openid-configuration
|
||||
CAOS_OIDC_DEV=1 go run github.com/caos/oidc/example/server/default
|
||||
# start oidc web client
|
||||
CLIENT_ID=web CLIENT_SECRET=web ISSUER=http://localhost:9998/ SCOPES=openid PORT=5556 go run github.com/caos/oidc/example/client/app
|
||||
```
|
||||
|
||||
- browser http://localhost:5556/login will redirect to op server
|
||||
- input id to login
|
||||
- redirect to client app display user info
|
||||
|
||||
## Features
|
||||
|
||||
| | Code Flow | Implicit Flow | Hybrid Flow | Discovery | PKCE | Token Exchange | mTLS | JWT Profile | Refresh Token |
|
||||
|----------------|-----------|---------------|-------------|-----------|------|----------------|---------|-------------|---------------|
|
||||
| Relaying Party | yes | yes | not yet | yes | yes | partial | not yet | yes | yes |
|
||||
| Relaying Party | yes | no[^1] | no | yes | yes | partial | not yet | yes | yes |
|
||||
| Origin Party | yes | yes | not yet | yes | yes | not yet | not yet | yes | yes |
|
||||
|
||||
### Resources
|
||||
|
@ -56,7 +68,7 @@ As of 2020 there are not a lot of `OIDC` library's in `Go` which can handle serv
|
|||
|
||||
- [Certify this library as OP](https://openid.net/certification/#OPs)
|
||||
|
||||
### Other Go OpenID Connect library's
|
||||
### Other Go OpenID Connect libraries
|
||||
|
||||
[https://github.com/coreos/go-oidc](https://github.com/coreos/go-oidc)
|
||||
|
||||
|
@ -64,7 +76,7 @@ The `go-oidc` does only support `RP` and is not feasible to use as `OP` that's w
|
|||
|
||||
[https://github.com/ory/fosite](https://github.com/ory/fosite)
|
||||
|
||||
We did not choose `fosite` because it implements `OAuth 2.0` on its own and does not rely in the golang provided package. Nonetheless this is a great project.
|
||||
We did not choose `fosite` because it implements `OAuth 2.0` on its own and does not rely on the golang provided package. Nonetheless this is a great project.
|
||||
|
||||
## License
|
||||
|
||||
|
@ -73,3 +85,6 @@ The full functionality of this library is and stays open source and free to use
|
|||
See the exact licensing terms [here](./LICENSE)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
|
||||
[^1]: https://github.com/caos/oidc/issues/135#issuecomment-950563892
|
||||
|
|
|
@ -37,6 +37,7 @@ type AuthRequest struct {
|
|||
Nonce string
|
||||
ClientID string
|
||||
CodeChallenge *oidc.CodeChallenge
|
||||
State string
|
||||
}
|
||||
|
||||
func (a *AuthRequest) GetACR() string {
|
||||
|
@ -103,7 +104,7 @@ func (a *AuthRequest) GetScopes() []string {
|
|||
func (a *AuthRequest) SetCurrentScopes(scopes []string) {}
|
||||
|
||||
func (a *AuthRequest) GetState() string {
|
||||
return ""
|
||||
return a.State
|
||||
}
|
||||
|
||||
func (a *AuthRequest) GetSubject() string {
|
||||
|
@ -125,7 +126,7 @@ func (s *AuthStorage) Health(ctx context.Context) error {
|
|||
}
|
||||
|
||||
func (s *AuthStorage) CreateAuthRequest(_ context.Context, authReq *oidc.AuthRequest, _ string) (op.AuthRequest, error) {
|
||||
a = &AuthRequest{ID: "id", ClientID: authReq.ClientID, ResponseType: authReq.ResponseType, Nonce: authReq.Nonce, RedirectURI: authReq.RedirectURI}
|
||||
a = &AuthRequest{ID: "id", ClientID: authReq.ClientID, ResponseType: authReq.ResponseType, Nonce: authReq.Nonce, RedirectURI: authReq.RedirectURI, State: authReq.State}
|
||||
if authReq.CodeChallenge != "" {
|
||||
a.CodeChallenge = &oidc.CodeChallenge{
|
||||
Challenge: authReq.CodeChallenge,
|
||||
|
@ -217,7 +218,7 @@ func (s *AuthStorage) GetClientByClientID(_ context.Context, id string) (op.Clie
|
|||
accessTokenType = op.AccessTokenTypeJWT
|
||||
responseTypes = []oidc.ResponseType{oidc.ResponseTypeIDToken, oidc.ResponseTypeIDTokenOnly}
|
||||
}
|
||||
return &ConfClient{ID: id, applicationType: appType, authMethod: authMethod, accessTokenType: accessTokenType, responseTypes: responseTypes, devMode: false}, nil
|
||||
return &ConfClient{ID: id, applicationType: appType, authMethod: authMethod, accessTokenType: accessTokenType, responseTypes: responseTypes, devMode: false, grantTypes: []oidc.GrantType{oidc.GrantTypeCode}}, nil
|
||||
}
|
||||
|
||||
func (s *AuthStorage) AuthorizeClientIDSecret(_ context.Context, id string, _ string) error {
|
||||
|
|
|
@ -170,11 +170,11 @@ func NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI string, sco
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
config, err := client.Discover(rp.issuer, rp.httpClient)
|
||||
discoveryConfiguration, err := client.Discover(rp.issuer, rp.httpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endpoints := GetEndpoints(config)
|
||||
endpoints := GetEndpoints(discoveryConfiguration)
|
||||
rp.oauthConfig.Endpoint = endpoints.Endpoint
|
||||
rp.endpoints = endpoints
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ func ConcatenateJSON(first, second []byte) ([]byte, error) {
|
|||
if !bytes.HasPrefix(second, []byte{'{'}) {
|
||||
return nil, fmt.Errorf("jws: invalid JSON %s", second)
|
||||
}
|
||||
// check empty
|
||||
if len(first) == 2 {
|
||||
return second, nil
|
||||
}
|
||||
if len(second) == 2 {
|
||||
return first, nil
|
||||
}
|
||||
|
||||
first[len(first)-1] = ','
|
||||
first = append(first, second[1:]...)
|
||||
return first, nil
|
||||
|
|
|
@ -44,6 +44,36 @@ func TestConcatenateJSON(t *testing.T) {
|
|||
[]byte(`{"some": "thing","another": "thing"}`),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"first empty",
|
||||
args{
|
||||
[]byte(`{}`),
|
||||
[]byte(`{"some": "thing"}`),
|
||||
},
|
||||
|
||||
[]byte(`{"some": "thing"}`),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"second empty",
|
||||
args{
|
||||
[]byte(`{"some": "thing"}`),
|
||||
[]byte(`{}`),
|
||||
},
|
||||
|
||||
[]byte(`{"some": "thing"}`),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"both empty",
|
||||
args{
|
||||
[]byte(`{}`),
|
||||
[]byte(`{}`),
|
||||
},
|
||||
|
||||
[]byte(`{}`),
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -53,7 +83,7 @@ func TestConcatenateJSON(t *testing.T) {
|
|||
return
|
||||
}
|
||||
if !bytes.Equal(got, tt.want) {
|
||||
t.Errorf("ConcatenateJSON() got = %v, want %v", got, tt.want)
|
||||
t.Errorf("ConcatenateJSON() got = %v, want %v", string(got), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -360,6 +360,7 @@ func (i *userinfo) MarshalJSON() ([]byte, error) {
|
|||
func (i *userinfo) UnmarshalJSON(data []byte) error {
|
||||
type Alias userinfo
|
||||
a := &struct {
|
||||
Address *userInfoAddress `json:"address,omitempty"`
|
||||
*Alias
|
||||
UpdatedAt int64 `json:"update_at,omitempty"`
|
||||
}{
|
||||
|
@ -368,7 +369,7 @@ func (i *userinfo) UnmarshalJSON(data []byte) error {
|
|||
if err := json.Unmarshal(data, &a); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.Address = a.Address
|
||||
i.UpdatedAt = Time(time.Unix(a.UpdatedAt, 0).UTC())
|
||||
|
||||
if err := json.Unmarshal(data, &i.claims); err != nil {
|
||||
|
|
26
pkg/oidc/userinfo_test.go
Normal file
26
pkg/oidc/userinfo_test.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserInfoMarshal(t *testing.T) {
|
||||
userinfo := NewUserInfo()
|
||||
userinfo.SetSubject("test")
|
||||
userinfo.SetAddress(NewUserInfoAddress("Test 789\nPostfach 2", "", "", "", "", ""))
|
||||
userinfo.SetEmail("test", true)
|
||||
userinfo.SetPhone("0791234567", true)
|
||||
userinfo.SetName("Test")
|
||||
userinfo.AppendClaims("private_claim", "test")
|
||||
|
||||
marshal, err := json.Marshal(userinfo)
|
||||
out := NewUserInfo()
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, json.Unmarshal(marshal, out))
|
||||
assert.Equal(t, userinfo.GetAddress(), out.GetAddress())
|
||||
expected, err := json.Marshal(out)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, marshal)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue