1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

Login via OpenID-2.0 (#618)

This commit is contained in:
Sandro Santilli
2017-03-17 15:16:08 +01:00
committed by Kim "BKC" Carlbäcker
parent 0693fbfc00
commit 71d16f69ff
44 changed files with 2298 additions and 57 deletions

View File

@@ -0,0 +1,59 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package openid
import (
"sync"
"time"
"github.com/yohcop/openid-go"
)
type timedDiscoveredInfo struct {
info openid.DiscoveredInfo
time time.Time
}
type timedDiscoveryCache struct {
cache map[string]timedDiscoveredInfo
ttl time.Duration
mutex *sync.Mutex
}
func newTimedDiscoveryCache(ttl time.Duration) *timedDiscoveryCache {
return &timedDiscoveryCache{cache: map[string]timedDiscoveredInfo{}, ttl: ttl, mutex: &sync.Mutex{}}
}
func (s *timedDiscoveryCache) Put(id string, info openid.DiscoveredInfo) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.cache[id] = timedDiscoveredInfo{info: info, time: time.Now()}
}
// Delete timed-out cache entries
func (s *timedDiscoveryCache) cleanTimedOut() {
now := time.Now()
for k, e := range s.cache {
diff := now.Sub(e.time)
if diff > s.ttl {
delete(s.cache, k)
}
}
}
func (s *timedDiscoveryCache) Get(id string) openid.DiscoveredInfo {
s.mutex.Lock()
defer s.mutex.Unlock()
// Delete old cached while we are at it.
s.cleanTimedOut()
if info, has := s.cache[id]; has {
return info.info
}
return nil
}

View File

@@ -0,0 +1,47 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package openid
import (
"testing"
"time"
)
type testDiscoveredInfo struct {}
func (s *testDiscoveredInfo) ClaimedID() string {
return "claimedID"
}
func (s *testDiscoveredInfo) OpEndpoint() string {
return "opEndpoint"
}
func (s *testDiscoveredInfo) OpLocalID() string {
return "opLocalID"
}
func TestTimedDiscoveryCache(t *testing.T) {
dc := newTimedDiscoveryCache(1*time.Second)
// Put some initial values
dc.Put("foo", &testDiscoveredInfo{}) //openid.opEndpoint: "a", openid.opLocalID: "b", openid.claimedID: "c"})
// Make sure we can retrieve them
if di := dc.Get("foo"); di == nil {
t.Errorf("Expected a result, got nil")
} else if di.OpEndpoint() != "opEndpoint" || di.OpLocalID() != "opLocalID" || di.ClaimedID() != "claimedID" {
t.Errorf("Expected opEndpoint opLocalID claimedID, got %v %v %v", di.OpEndpoint(), di.OpLocalID(), di.ClaimedID())
}
// Attempt to get a non-existent value
if di := dc.Get("bar"); di != nil {
t.Errorf("Expected nil, got %v", di)
}
// Sleep one second and try retrive again
time.Sleep(1 * time.Second)
if di := dc.Get("foo"); di != nil {
t.Errorf("Expected a nil, got a result")
}
}

View File

@@ -0,0 +1,37 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package openid
import (
"github.com/yohcop/openid-go"
"time"
)
// For the demo, we use in-memory infinite storage nonce and discovery
// cache. In your app, do not use this as it will eat up memory and
// never
// free it. Use your own implementation, on a better database system.
// If you have multiple servers for example, you may need to share at
// least
// the nonceStore between them.
var nonceStore = openid.NewSimpleNonceStore()
var discoveryCache = newTimedDiscoveryCache(24*time.Hour)
// Verify handles response from OpenID provider
func Verify(fullURL string) (id string, err error) {
return openid.Verify(fullURL, discoveryCache, nonceStore)
}
// Normalize normalizes an OpenID URI
func Normalize(url string) (id string, err error) {
return openid.Normalize(url)
}
// RedirectURL redirects browser
func RedirectURL(id, callbackURL, realm string) (string, error) {
return openid.RedirectURL(id, callbackURL, realm)
}