mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-02-01 15:34:25 +00:00
fix(security): 🐛 handle errors in OAuth2 examples and passkey methods
Some checks failed
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in -22m52s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in -22m42s
Build , Vet Test, and Lint / Build (push) Successful in -26m19s
Build , Vet Test, and Lint / Lint Code (push) Successful in -25m40s
Tests / Unit Tests (push) Successful in -26m33s
Tests / Integration Tests (push) Failing after -26m55s
Some checks failed
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in -22m52s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in -22m42s
Build , Vet Test, and Lint / Build (push) Successful in -26m19s
Build , Vet Test, and Lint / Lint Code (push) Successful in -25m40s
Tests / Unit Tests (push) Successful in -26m33s
Tests / Integration Tests (push) Failing after -26m55s
* Add error handling for JSON encoding and HTTP server calls. * Update passkey examples to improve readability and maintainability. * Ensure consistent use of error handling across all examples.
This commit is contained in:
@@ -54,10 +54,10 @@ func ExampleOAuth2Google() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Return user info as JSON
|
// Return user info as JSON
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: OAuth2 Authentication with GitHub
|
// Example: OAuth2 Authentication with GitHub
|
||||||
@@ -89,10 +89,10 @@ func ExampleOAuth2GitHub() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: Custom OAuth2 Provider
|
// Example: Custom OAuth2 Provider
|
||||||
@@ -142,10 +142,10 @@ func ExampleOAuth2Custom() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: Multi-Provider OAuth2 with Security Integration
|
// Example: Multi-Provider OAuth2 with Security Integration
|
||||||
@@ -240,10 +240,10 @@ func ExampleOAuth2MultiProvider() {
|
|||||||
|
|
||||||
protectedRouter.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
|
protectedRouter.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
|
||||||
userCtx, _ := GetUserContext(r.Context())
|
userCtx, _ := GetUserContext(r.Context())
|
||||||
json.NewEncoder(w).Encode(userCtx)
|
_ = json.NewEncoder(w).Encode(userCtx)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: OAuth2 with Token Refresh
|
// Example: OAuth2 with Token Refresh
|
||||||
@@ -294,10 +294,10 @@ func ExampleOAuth2TokenRefresh() {
|
|||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
})
|
})
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: OAuth2 Logout
|
// Example: OAuth2 Logout
|
||||||
@@ -326,7 +326,7 @@ func ExampleOAuth2Logout() {
|
|||||||
// Get user ID from session
|
// Get user ID from session
|
||||||
userCtx, err := oauth2Auth.Authenticate(r)
|
userCtx, err := oauth2Auth.Authenticate(r)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
oauth2Auth.Logout(r.Context(), LogoutRequest{
|
_ = oauth2Auth.Logout(r.Context(), LogoutRequest{
|
||||||
Token: token,
|
Token: token,
|
||||||
UserID: userCtx.UserID,
|
UserID: userCtx.UserID,
|
||||||
})
|
})
|
||||||
@@ -343,10 +343,10 @@ func ExampleOAuth2Logout() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte("Logged out successfully"))
|
_, _ = w.Write([]byte("Logged out successfully"))
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example: Complete OAuth2 Integration with Database Setup
|
// Example: Complete OAuth2 Integration with Database Setup
|
||||||
@@ -374,7 +374,7 @@ func ExampleOAuth2Complete() {
|
|||||||
|
|
||||||
// Public routes
|
// Public routes
|
||||||
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("Welcome! <a href='/auth/google/login'>Login with Google</a>"))
|
_, _ = w.Write([]byte("Welcome! <a href='/auth/google/login'>Login with Google</a>"))
|
||||||
})
|
})
|
||||||
|
|
||||||
router.HandleFunc("/auth/google/login", func(w http.ResponseWriter, r *http.Request) {
|
router.HandleFunc("/auth/google/login", func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -411,17 +411,17 @@ func ExampleOAuth2Complete() {
|
|||||||
|
|
||||||
protectedRouter.HandleFunc("/dashboard", func(w http.ResponseWriter, r *http.Request) {
|
protectedRouter.HandleFunc("/dashboard", func(w http.ResponseWriter, r *http.Request) {
|
||||||
userCtx, _ := GetUserContext(r.Context())
|
userCtx, _ := GetUserContext(r.Context())
|
||||||
w.Write([]byte(fmt.Sprintf("Welcome, %s! Your email: %s", userCtx.UserName, userCtx.Email)))
|
_, _ = fmt.Fprintf(w, "Welcome, %s! Your email: %s", userCtx.UserName, userCtx.Email)
|
||||||
})
|
})
|
||||||
|
|
||||||
protectedRouter.HandleFunc("/api/profile", func(w http.ResponseWriter, r *http.Request) {
|
protectedRouter.HandleFunc("/api/profile", func(w http.ResponseWriter, r *http.Request) {
|
||||||
userCtx, _ := GetUserContext(r.Context())
|
userCtx, _ := GetUserContext(r.Context())
|
||||||
json.NewEncoder(w).Encode(userCtx)
|
_ = json.NewEncoder(w).Encode(userCtx)
|
||||||
})
|
})
|
||||||
|
|
||||||
protectedRouter.HandleFunc("/auth/logout", func(w http.ResponseWriter, r *http.Request) {
|
protectedRouter.HandleFunc("/auth/logout", func(w http.ResponseWriter, r *http.Request) {
|
||||||
userCtx, _ := GetUserContext(r.Context())
|
userCtx, _ := GetUserContext(r.Context())
|
||||||
oauth2Auth.Logout(r.Context(), LogoutRequest{
|
_ = oauth2Auth.Logout(r.Context(), LogoutRequest{
|
||||||
Token: userCtx.SessionID,
|
Token: userCtx.SessionID,
|
||||||
UserID: userCtx.UserID,
|
UserID: userCtx.UserID,
|
||||||
})
|
})
|
||||||
@@ -437,7 +437,7 @@ func ExampleOAuth2Complete() {
|
|||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupOAuth2Tables(db *sql.DB) {
|
func setupOAuth2Tables(db *sql.DB) {
|
||||||
@@ -446,7 +446,7 @@ func setupOAuth2Tables(db *sql.DB) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// Create users table if not exists
|
// Create users table if not exists
|
||||||
db.ExecContext(ctx, `
|
_, _ = db.ExecContext(ctx, `
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
username VARCHAR(255) NOT NULL UNIQUE,
|
username VARCHAR(255) NOT NULL UNIQUE,
|
||||||
@@ -464,7 +464,7 @@ func setupOAuth2Tables(db *sql.DB) {
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
// Create user_sessions table (used for both regular and OAuth2 sessions)
|
// Create user_sessions table (used for both regular and OAuth2 sessions)
|
||||||
db.ExecContext(ctx, `
|
_, _ = db.ExecContext(ctx, `
|
||||||
CREATE TABLE IF NOT EXISTS user_sessions (
|
CREATE TABLE IF NOT EXISTS user_sessions (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
session_token VARCHAR(500) NOT NULL UNIQUE,
|
session_token VARCHAR(500) NOT NULL UNIQUE,
|
||||||
@@ -547,7 +547,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
// GitHub routes
|
// GitHub routes
|
||||||
@@ -562,7 +562,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Microsoft routes
|
// Microsoft routes
|
||||||
@@ -577,7 +577,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Facebook routes
|
// Facebook routes
|
||||||
@@ -592,7 +592,7 @@ func ExampleOAuth2AllProviders() {
|
|||||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(loginResp)
|
_ = json.NewEncoder(w).Encode(loginResp)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create security list for protected routes
|
// Create security list for protected routes
|
||||||
@@ -608,8 +608,8 @@ func ExampleOAuth2AllProviders() {
|
|||||||
|
|
||||||
protectedRouter.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
|
protectedRouter.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
|
||||||
userCtx, _ := GetUserContext(r.Context())
|
userCtx, _ := GetUserContext(r.Context())
|
||||||
json.NewEncoder(w).Encode(userCtx)
|
_ = json.NewEncoder(w).Encode(userCtx)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":8080", router)
|
_ = http.ListenAndServe(":8080", router)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -570,6 +570,7 @@ func NewFacebookAuthenticator(clientID, clientSecret, redirectURL string, db *sq
|
|||||||
func NewMultiProviderAuthenticator(db *sql.DB, configs map[string]OAuth2Config) *DatabaseAuthenticator {
|
func NewMultiProviderAuthenticator(db *sql.DB, configs map[string]OAuth2Config) *DatabaseAuthenticator {
|
||||||
auth := NewDatabaseAuthenticator(db)
|
auth := NewDatabaseAuthenticator(db)
|
||||||
|
|
||||||
|
//nolint:gocritic // OAuth2Config is copied but kept for API simplicity
|
||||||
for _, cfg := range configs {
|
for _, cfg := range configs {
|
||||||
auth.WithOAuth2(cfg)
|
auth.WithOAuth2(cfg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,13 @@ func PasskeyAuthenticationExample() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Create authenticator with passkey support
|
// Create authenticator with passkey support
|
||||||
auth := NewDatabaseAuthenticatorWithOptions(db, DatabaseAuthenticatorOptions{
|
// Option 1: Pass during creation
|
||||||
|
_ = NewDatabaseAuthenticatorWithOptions(db, DatabaseAuthenticatorOptions{
|
||||||
PasskeyProvider: passkeyProvider,
|
PasskeyProvider: passkeyProvider,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Or use WithPasskey method
|
// Option 2: Use WithPasskey method
|
||||||
auth = NewDatabaseAuthenticator(db).WithPasskey(passkeyProvider)
|
auth := NewDatabaseAuthenticator(db).WithPasskey(passkeyProvider)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
@@ -106,9 +107,9 @@ func PasskeyAuthenticationExample() {
|
|||||||
|
|
||||||
// Get all credentials for a user
|
// Get all credentials for a user
|
||||||
credentials, _ := auth.GetPasskeyCredentials(ctx, 1)
|
credentials, _ := auth.GetPasskeyCredentials(ctx, 1)
|
||||||
for _, cred := range credentials {
|
for i := range credentials {
|
||||||
fmt.Printf("Credential: %s (created: %s, last used: %s)\n",
|
fmt.Printf("Credential: %s (created: %s, last used: %s)\n",
|
||||||
cred.Name, cred.CreatedAt, cred.LastUsedAt)
|
credentials[i].Name, credentials[i].CreatedAt, credentials[i].LastUsedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update credential name
|
// Update credential name
|
||||||
@@ -130,7 +131,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
}
|
}
|
||||||
json.NewDecoder(r.Body).Decode(&req)
|
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
|
||||||
options, err := auth.BeginPasskeyRegistration(r.Context(), PasskeyBeginRegistrationRequest{
|
options, err := auth.BeginPasskeyRegistration(r.Context(), PasskeyBeginRegistrationRequest{
|
||||||
UserID: req.UserID,
|
UserID: req.UserID,
|
||||||
@@ -147,7 +148,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
challenges[sessionID] = options.Challenge
|
challenges[sessionID] = options.Challenge
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(options)
|
_ = json.NewEncoder(w).Encode(options)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Complete registration endpoint
|
// Complete registration endpoint
|
||||||
@@ -157,7 +158,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
Response PasskeyRegistrationResponse `json:"response"`
|
Response PasskeyRegistrationResponse `json:"response"`
|
||||||
CredentialName string `json:"credential_name"`
|
CredentialName string `json:"credential_name"`
|
||||||
}
|
}
|
||||||
json.NewDecoder(r.Body).Decode(&req)
|
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
|
||||||
// Get stored challenge (from session in production)
|
// Get stored challenge (from session in production)
|
||||||
sessionID := "session-123"
|
sessionID := "session-123"
|
||||||
@@ -176,7 +177,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(credential)
|
_ = json.NewEncoder(w).Encode(credential)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Begin authentication endpoint
|
// Begin authentication endpoint
|
||||||
@@ -184,7 +185,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
var req struct {
|
var req struct {
|
||||||
Username string `json:"username"` // Optional
|
Username string `json:"username"` // Optional
|
||||||
}
|
}
|
||||||
json.NewDecoder(r.Body).Decode(&req)
|
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
|
||||||
options, err := auth.BeginPasskeyAuthentication(r.Context(), PasskeyBeginAuthenticationRequest{
|
options, err := auth.BeginPasskeyAuthentication(r.Context(), PasskeyBeginAuthenticationRequest{
|
||||||
Username: req.Username,
|
Username: req.Username,
|
||||||
@@ -199,7 +200,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
challenges[sessionID] = options.Challenge
|
challenges[sessionID] = options.Challenge
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(options)
|
_ = json.NewEncoder(w).Encode(options)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Complete authentication endpoint
|
// Complete authentication endpoint
|
||||||
@@ -207,7 +208,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
var req struct {
|
var req struct {
|
||||||
Response PasskeyAuthenticationResponse `json:"response"`
|
Response PasskeyAuthenticationResponse `json:"response"`
|
||||||
}
|
}
|
||||||
json.NewDecoder(r.Body).Decode(&req)
|
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
|
||||||
// Get stored challenge (from session in production)
|
// Get stored challenge (from session in production)
|
||||||
sessionID := "session-456"
|
sessionID := "session-456"
|
||||||
@@ -238,7 +239,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(loginResponse)
|
_ = json.NewEncoder(w).Encode(loginResponse)
|
||||||
})
|
})
|
||||||
|
|
||||||
// List credentials endpoint
|
// List credentials endpoint
|
||||||
@@ -257,7 +258,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(credentials)
|
_ = json.NewEncoder(w).Encode(credentials)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Delete credential endpoint
|
// Delete credential endpoint
|
||||||
@@ -271,7 +272,7 @@ func PasskeyHTTPHandlersExample(auth *DatabaseAuthenticator) {
|
|||||||
var req struct {
|
var req struct {
|
||||||
CredentialID string `json:"credential_id"`
|
CredentialID string `json:"credential_id"`
|
||||||
}
|
}
|
||||||
json.NewDecoder(r.Body).Decode(&req)
|
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
|
||||||
err = auth.DeletePasskeyCredential(r.Context(), userCtx.UserID, req.CredentialID)
|
err = auth.DeletePasskeyCredential(r.Context(), userCtx.UserID, req.CredentialID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ func (p *DatabasePasskeyProvider) BeginRegistration(ctx context.Context, userID
|
|||||||
}
|
}
|
||||||
|
|
||||||
excludeCredentials := make([]PasskeyCredentialDescriptor, 0, len(credentials))
|
excludeCredentials := make([]PasskeyCredentialDescriptor, 0, len(credentials))
|
||||||
for _, cred := range credentials {
|
for i := range credentials {
|
||||||
excludeCredentials = append(excludeCredentials, PasskeyCredentialDescriptor{
|
excludeCredentials = append(excludeCredentials, PasskeyCredentialDescriptor{
|
||||||
Type: "public-key",
|
Type: "public-key",
|
||||||
ID: cred.CredentialID,
|
ID: credentials[i].CredentialID,
|
||||||
Transports: cred.Transports,
|
Transports: credentials[i].Transports,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +319,8 @@ func (p *DatabasePasskeyProvider) GetCredentials(ctx context.Context, userID int
|
|||||||
}
|
}
|
||||||
|
|
||||||
credentials := make([]PasskeyCredential, 0, len(rawCreds))
|
credentials := make([]PasskeyCredential, 0, len(rawCreds))
|
||||||
for _, raw := range rawCreds {
|
for i := range rawCreds {
|
||||||
|
raw := rawCreds[i]
|
||||||
credID, err := base64.StdEncoding.DecodeString(raw.CredentialID)
|
credID, err := base64.StdEncoding.DecodeString(raw.CredentialID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user