Skip to content

Commit

Permalink
add multiple handlers to profile api
Browse files Browse the repository at this point in the history
  • Loading branch information
greenpau committed Mar 22, 2024
1 parent 68df1f9 commit 0454e12
Show file tree
Hide file tree
Showing 16 changed files with 529 additions and 28 deletions.
4 changes: 2 additions & 2 deletions pkg/authn/api_add_user_app_multi_factor_authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,18 @@ func (p *Portal) AddUserAppMultiFactorVerifier(
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}

rr.MfaToken.Type = "totp"
rr.MfaToken.SkipVerification = true
rr.MfaToken.Comment = tokenTitle
rr.MfaToken.Description = tokenDescription
rr.MfaToken.Secret = tokenSecret
rr.MfaToken.Type = "totp"
rr.MfaToken.Period = tokenLifetime
rr.MfaToken.Digits = tokenDigits
rr.MfaToken.Labels = tokenLabels
rr.MfaToken.Tags = tokenTags

if err := backend.Request(operator.AddMfaToken, rr); err != nil {
resp["message"] = "Profile API failed to add token identity store"
resp["message"] = "Profile API failed to add token to identity store"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}

Expand Down
107 changes: 107 additions & 0 deletions pkg/authn/api_add_user_u2f_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2024 Paul Greenberg [email protected]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.

package authn

import (
"context"
"net/http"

"github.com/greenpau/go-authcrunch/pkg/authn/enums/operator"
"github.com/greenpau/go-authcrunch/pkg/ids"
"github.com/greenpau/go-authcrunch/pkg/requests"
"github.com/greenpau/go-authcrunch/pkg/tagging"
"github.com/greenpau/go-authcrunch/pkg/user"
)

// AddUserUniSecFactorToken adds U2F token to user identity.
func (p *Portal) AddUserUniSecFactorToken(
ctx context.Context,
w http.ResponseWriter,
r *http.Request,
rr *requests.Request,
parsedUser *user.User,
resp map[string]interface{},
usr *user.User,
backend ids.IdentityStore,
bodyData map[string]interface{}) error {

var tokenTitle, tokenDescription string
var tokenLabels []string = []string{}
var tokenTags []tagging.Tag = []tagging.Tag{}

// Validate inputs.
if v, exists := bodyData["webauthn_register"]; exists {
rr.WebAuthn.Register = v.(string)
} else {
resp["message"] = "Profile API did not find webauthn_register in the request payload"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}
if v, exists := bodyData["webauthn_challenge"]; exists {
rr.WebAuthn.Challenge = v.(string)
} else {
resp["message"] = "Profile API did not find webauthn_challenge in the request payload"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}
if v, exists := bodyData["title"]; exists {
tokenTitle = v.(string)
} else {
resp["message"] = "Profile API did not find title in the request payload"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}
if v, exists := bodyData["description"]; exists {
tokenDescription = v.(string)
} else {
resp["message"] = "Profile API did not find description in the request payload"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}
if extractedTokenTags, err := tagging.ExtractTags(bodyData); err == nil {
for _, extractedTokenTag := range extractedTokenTags {
tokenTags = append(tokenTags, *extractedTokenTag)
}
} else {
resp["message"] = "Profile API find malformed tags in the request payload"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}
if extractedTokenLabels, err := tagging.ExtractLabels(bodyData); err == nil {
tokenLabels = extractedTokenLabels
} else {
resp["message"] = "Profile API find malformed tags in the request payload"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}

// Validate data.
if !tokenIssuerRegexPattern.MatchString(tokenTitle) {
resp["message"] = "Profile API found non-compliant token title value"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}
if !tokenDescriptionRegexPattern.MatchString(tokenDescription) && (tokenDescription != "") {
resp["message"] = "Profile API found non-compliant token description value"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}

rr.MfaToken.Type = "u2f"
rr.MfaToken.Comment = tokenTitle
rr.MfaToken.Description = tokenDescription
rr.MfaToken.Tags = tokenTags
rr.MfaToken.Labels = tokenLabels

if err := backend.Request(operator.AddMfaToken, rr); err != nil {
resp["message"] = "Profile API failed to add token to identity store"
return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp)
}

resp["entry"] = "Created"
return handleAPIProfileResponse(w, rr, http.StatusOK, resp)
}
8 changes: 4 additions & 4 deletions pkg/authn/api_fetch_user_api_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ func (p *Portal) FetchUserAPIKeys(
bundle := rr.Response.Payload.(*identity.APIKeyBundle)

apiKeys := bundle.Get()
for _, apiKey := range apiKeys {
apiKey.Payload = ""
apiKey.Prefix = ""
}
// for _, apiKey := range apiKeys {
// apiKey.Payload = ""
// apiKey.Prefix = ""
// }
resp["entries"] = apiKeys
return handleAPIProfileResponse(w, rr, http.StatusOK, resp)
}
Expand Down
6 changes: 5 additions & 1 deletion pkg/authn/api_fetch_user_dashboard_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"go.uber.org/zap"
)

// FetchUserDashboardData fetches user identity information.
// FetchUserDashboardData fetches user dashboard information.
func (p *Portal) FetchUserDashboardData(
ctx context.Context,
w http.ResponseWriter,
Expand Down Expand Up @@ -58,6 +58,7 @@ func (p *Portal) FetchUserDashboardData(

// API Keys
rr.Key.Usage = "api"
rr.Key.IncludeAll = true
err = backend.Request(operator.GetAPIKeys, rr)
if err != nil {
resp["message"] = "failed to extract user api keys"
Expand All @@ -75,6 +76,7 @@ func (p *Portal) FetchUserDashboardData(

// SSH Keys
rr.Key.Usage = "ssh"
rr.Key.IncludeAll = true
err = backend.Request(operator.GetPublicKeys, rr)
if err != nil {
resp["message"] = "failed to extract user ssh keys"
Expand All @@ -92,6 +94,7 @@ func (p *Portal) FetchUserDashboardData(

// GPG Keys
rr.Key.Usage = "gpg"
rr.Key.IncludeAll = true
err = backend.Request(operator.GetPublicKeys, rr)
if err != nil {
resp["message"] = "failed to extract user gpg keys"
Expand All @@ -108,6 +111,7 @@ func (p *Portal) FetchUserDashboardData(
assetCount["gpg_key"] = len(gpgKeys)

// MFA and 2FA
rr.MfaToken.IncludeAll = true
if err := backend.Request(operator.GetMfaTokens, rr); err != nil {
resp["message"] = "failed to extract user MFA/2FA"
return handleAPIProfileResponse(w, rr, http.StatusInternalServerError, resp)
Expand Down
96 changes: 96 additions & 0 deletions pkg/authn/api_fetch_user_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2024 Paul Greenberg [email protected]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// 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.

package authn

import (
"context"
"encoding/json"
"net/http"
"time"

"github.com/greenpau/go-authcrunch/pkg/authn/enums/operator"
"github.com/greenpau/go-authcrunch/pkg/identity"
"github.com/greenpau/go-authcrunch/pkg/ids"
"github.com/greenpau/go-authcrunch/pkg/requests"
"github.com/greenpau/go-authcrunch/pkg/user"
"go.uber.org/zap"
)

// FetchUserInfo fetches user identity information.
func (p *Portal) FetchUserInfo(
ctx context.Context,
w http.ResponseWriter,
r *http.Request,
rr *requests.Request,
parsedUser *user.User,
resp map[string]interface{},
usr *user.User,
backend ids.IdentityStore) error {

// Data Buckets
entry := make(map[string]interface{})

// General Info
err := backend.Request(operator.GetUser, rr)
if err != nil {
resp["message"] = "failed to extract user metadata"
p.logger.Debug(
"failed to extract user metadata",
zap.String("session_id", rr.Upstream.SessionID),
zap.String("request_id", rr.ID),
zap.Error(err),
)
return handleAPIProfileResponse(w, rr, http.StatusInternalServerError, resp)
}
user := rr.Response.Payload.(*identity.User)
entry["metadata"] = user.GetMetadata()

// User Roles

entry["roles"] = parsedUser.Claims.Roles

// Token

tokenMap := make(map[string]interface{})
for k, v := range usr.AsMap() {
tokenMap[k] = v
}
tokenMap["authenticated"] = true
if usr.Claims.ExpiresAt > 0 {
tokenMap["expires_at_utc"] = time.Unix(usr.Claims.ExpiresAt, 0).Format(time.UnixDate)
}
if usr.Claims.IssuedAt > 0 {
tokenMap["issued_at_utc"] = time.Unix(usr.Claims.IssuedAt, 0).Format(time.UnixDate)
}
if usr.Claims.NotBefore > 0 {
tokenMap["not_before_utc"] = time.Unix(usr.Claims.NotBefore, 0).Format(time.UnixDate)
}
prettyTokenMap, err := json.MarshalIndent(tokenMap, "", " ")
if err != nil {
p.logger.Debug(
"failed to prettify user token",
zap.String("session_id", rr.Upstream.SessionID),
zap.String("request_id", rr.ID),
zap.Error(err),
)
return handleAPIProfileResponse(w, rr, http.StatusInternalServerError, resp)
}
entry["token"] = string(prettyTokenMap)

// Finalize

resp["entry"] = entry
return handleAPIProfileResponse(w, rr, http.StatusOK, resp)
}
7 changes: 4 additions & 3 deletions pkg/authn/api_fetch_user_multi_factor_authenticators.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@ func (p *Portal) FetchUserMultiFactorVerifiers(
backend ids.IdentityStore) error {

// List MFA Tokens.
rr.MfaToken.IncludeAll = true
if err := backend.Request(operator.GetMfaTokens, rr); err != nil {
resp["message"] = "Profile API failed to get user multi factor authenticators"
return handleAPIProfileResponse(w, rr, http.StatusInternalServerError, resp)
}
bundle := rr.Response.Payload.(*identity.MfaTokenBundle)

tokens := bundle.Get()
for _, token := range tokens {
token.Secret = ""
}
// for _, token := range tokens {
// token.Secret = ""
// }
resp["entries"] = tokens
return handleAPIProfileResponse(w, rr, http.StatusOK, resp)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/authn/api_fetch_user_ssh_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ func (p *Portal) FetchUserSSHKeys(
}
bundle := rr.Response.Payload.(*identity.PublicKeyBundle)
sshKeys := bundle.Get()
for _, sshKey := range sshKeys {
sshKey.Payload = ""
sshKey.OpenSSH = ""
}
// for _, sshKey := range sshKeys {
// sshKey.Payload = ""
// sshKey.OpenSSH = ""
// }
resp["entries"] = sshKeys

return handleAPIProfileResponse(w, rr, http.StatusOK, resp)
Expand Down
5 changes: 4 additions & 1 deletion pkg/authn/api_fetch_user_uni_sec_factor_reg_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ package authn

import (
"context"
"encoding/base64"
"net/http"
"strings"

"github.com/greenpau/go-authcrunch/pkg/ids"
"github.com/greenpau/go-authcrunch/pkg/requests"
Expand All @@ -37,7 +39,8 @@ func (p *Portal) FetchUserUniSecFactorRegParams(
bodyData map[string]interface{}) error {

params := make(map[string]interface{})
params["challenge"] = util.GetRandomStringFromRange(64, 92)
randomStr := util.GetRandomStringFromRange(64, 92)
params["challenge"] = strings.TrimRight(base64.StdEncoding.EncodeToString([]byte(randomStr)), "=")
params["rp_name"] = "AuthCrunch"
// params["rp_id"] = "auth.authcrunch.com"
params["user_id"] = usr.Claims.ID
Expand Down
Loading

0 comments on commit 0454e12

Please sign in to comment.