Exemple #1
0
func (s *grpcServer) Token(userID, clientID string, iat, exp time.Time) (*jose.JWT, string, error) {
	signer, err := s.server.KeyManager.Signer()
	if err != nil {
		log.Errorf("grpc.go: Failed to generate ID token: %v", err)
		return nil, "", oauth2.NewError(oauth2.ErrorServerError)
	}

	user, err := s.server.UserRepo.Get(nil, userID)
	if err != nil {
		log.Errorf("grpc.go: Failed to fetch user %q from repo: %v: ", userID, err)
		return nil, "", oauth2.NewError(oauth2.ErrorServerError)
	}
	claims := oidc.NewClaims(s.server.IssuerURL.String(), userID, clientID, iat, exp)
	user.AddToClaims(claims)

	if user.Admin {
		claims.Add(OtsimoUserTypeClaim, "adm")
	}

	jwt, err := jose.NewSignedJWT(claims, signer)
	if err != nil {
		log.Errorf("grpc.go: Failed to generate ID token: %v", err)
		return nil, "", oauth2.NewError(oauth2.ErrorServerError)
	}

	refreshToken, err := s.server.RefreshTokenRepo.Create(user.ID, clientID)
	if err != nil {
		log.Errorf("grpc.go: Failed to generate refresh token: %v", err)
		return nil, "", oauth2.NewError(oauth2.ErrorServerError)
	}

	return jwt, refreshToken, nil
}
Exemple #2
0
func (s *Server) ClientCredsToken(creds oidc.ClientCredentials) (*jose.JWT, error) {
	ok, err := s.ClientIdentityRepo.Authenticate(creds)
	if err != nil {
		log.Errorf("Failed fetching client %s from repo: %v", creds.ID, err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}
	if !ok {
		return nil, oauth2.NewError(oauth2.ErrorInvalidClient)
	}

	signer, err := s.KeyManager.Signer()
	if err != nil {
		log.Errorf("Failed to generate ID token: %v", err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	now := time.Now()
	exp := now.Add(s.SessionManager.ValidityWindow)
	claims := oidc.NewClaims(s.IssuerURL.String(), creds.ID, creds.ID, now, exp)
	claims.Add("name", creds.ID)

	jwt, err := jose.NewSignedJWT(claims, signer)
	if err != nil {
		log.Errorf("Failed to generate ID token: %v", err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	log.Infof("Client token sent: clientID=%s", creds.ID)

	return jwt, nil
}
Exemple #3
0
func (s *Server) handleClientRegistrationRequest(r *http.Request) (*oidc.ClientRegistrationResponse, *apiError) {
	var clientMetadata oidc.ClientMetadata
	if err := json.NewDecoder(r.Body).Decode(&clientMetadata); err != nil {
		return nil, newAPIError(oauth2.ErrorInvalidRequest, err.Error())
	}
	if err := s.ProviderConfig().Supports(clientMetadata); err != nil {
		return nil, newAPIError(invalidClientMetadata, err.Error())
	}

	// metadata is guarenteed to have at least one redirect_uri by earlier validation.
	id, err := oidc.GenClientID(clientMetadata.RedirectURIs[0].Host)
	if err != nil {
		log.Errorf("Faild to create client ID: %v", err)
		return nil, newAPIError(oauth2.ErrorServerError, "unable to save client metadata")
	}

	creds, err := s.ClientIdentityRepo.New(id, clientMetadata)
	if err != nil {
		log.Errorf("Failed to create new client identity: %v", err)
		return nil, newAPIError(oauth2.ErrorServerError, "unable to save client metadata")
	}

	return &oidc.ClientRegistrationResponse{
		ClientID:       creds.ID,
		ClientSecret:   creds.Secret,
		ClientMetadata: clientMetadata,
	}, nil
}
Exemple #4
0
func (g *grpcServer) ChangeEmail(ctx context.Context, in *pb.ChangeEmailRequest) (*pb.Response, error) {
	jwtClient, err := getJWTToken(ctx)
	if err != nil {
		log.Errorf("grpc.go: getJWTToken error %v", err)
		return nil, err
	}
	_, _, err = g.authToken(jwtClient)
	if err != nil {
		log.Errorf("grpc.go: authToken failed error=%v", err)
		return nil, err
	}
	u, err := g.server.UserRepo.GetByEmail(nil, in.OldEmail)
	if err != nil {
		log.Errorf("grpc.go: change email user not found =%v", err)
		return nil, err
	}
	err = g.server.UserRepo.Update(nil, user.User{
		ID:    u.ID,
		Email: in.NewEmail,
	})
	if err != nil {
		log.Errorf("grpc.go: failed to change email of user %+v", err)
		return nil, err
	}
	return &pb.Response{Type: 0}, nil
}
Exemple #5
0
func (r *clientIdentityRepo) Authenticate(creds oidc.ClientCredentials) (bool, error) {
	m, err := r.executor(nil).Get(clientIdentityModel{}, creds.ID)
	if m == nil || err != nil {
		return false, err
	}

	cim, ok := m.(*clientIdentityModel)
	if !ok {
		log.Errorf("expected clientIdentityModel but found %v", reflect.TypeOf(m))
		return false, errors.New("unrecognized model")
	}

	dec, err := base64.URLEncoding.DecodeString(creds.Secret)
	if err != nil {
		log.Errorf("error Decoding client creds: %v", err)
		return false, nil
	}

	if len(dec) > maxSecretLength {
		return false, nil
	}

	ok = bcrypt.CompareHashAndPassword(cim.Secret, dec) == nil
	return ok, nil
}
Exemple #6
0
func registerUser(o *OtsimoAccounts, email, password, firstName, lastName, language string) (*pb.RegisterResponse, error) {
	resp, err := o.Dex.Register(context.Background(), &pb.RegisterRequest{
		Email:       email,
		DisplayName: fmt.Sprintf("%s %s", firstName, lastName),
		Password:    password,
	})

	log.Infof("register.go: register result of '%s' is %q %v", email, resp, err)
	if err != nil {
		return nil, err
	}
	_, errapi := o.Api.AddProfile(context.Background(), &apipb.Profile{
		Id:        bson.ObjectIdHex(resp.UserId),
		Email:     email,
		FirstName: firstName,
		LastName:  lastName,
		Language:  language,
	})
	if errapi != nil {
		//Disable or delete user
		log.Errorf("register.go: failed to add profile %+v", errapi)
		_, err = o.Dex.RemoveUser(context.Background(), &pb.RemoveRequest{Id: resp.UserId, Email: email})
		if err != nil {
			log.Errorf("register.go: Holly F**K!!: failed to add profile and remove user [error]=%+v [user_id]='%s' [user_email]='%s'", err, resp.UserId, email)
			return nil, err
		}
		return nil, fmt.Errorf("failed to register user, adding to api service failed:%v", errapi)
	}
	return resp, nil
}
Exemple #7
0
func (g *grpcServer) RemoveUser(ctx context.Context, in *pb.RemoveRequest) (*pb.Response, error) {
	jwtClient, err := getJWTToken(ctx)
	if err != nil {
		log.Errorf("grpc.go: getJWTToken error %v", err)
		return nil, err
	}
	_, _, err = g.authToken(jwtClient)
	if err != nil {
		log.Errorf("grpc.go: authToken failed error=%v", err)
		return nil, err
	}

	usr, err := g.server.UserManager.Get(in.Id)
	if err != nil {
		log.Errorf("grpc.go: failed to get user %+v", err)
		return nil, err
	}
	if usr.Email == in.Email {
		return nil, errors.New("given email is different than old one")
	}
	err = g.server.UserRepo.Update(nil, user.User{
		ID:       in.Id,
		Email:    fmt.Sprintf("$$%s$%s", randStringBytesRmndr(4), in.Email),
		Disabled: false,
	})
	if err != nil {
		log.Errorf("grpc.go: failed to update-remove user %+v", err)
		return nil, err
	}
	return &pb.Response{Type: 0}, nil
}
Exemple #8
0
func (s *Server) RefreshToken(creds oidc.ClientCredentials, token string) (*jose.JWT, error) {
	ok, err := s.ClientIdentityRepo.Authenticate(creds)
	if err != nil {
		log.Errorf("Failed fetching client %s from repo: %v", creds.ID, err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}
	if !ok {
		log.Errorf("Failed to Authenticate client %s", creds.ID)
		return nil, oauth2.NewError(oauth2.ErrorInvalidClient)
	}

	userID, err := s.RefreshTokenRepo.Verify(creds.ID, token)
	switch err {
	case nil:
		break
	case refresh.ErrorInvalidToken:
		return nil, oauth2.NewError(oauth2.ErrorInvalidRequest)
	case refresh.ErrorInvalidClientID:
		return nil, oauth2.NewError(oauth2.ErrorInvalidClient)
	default:
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	user, err := s.UserRepo.Get(nil, userID)
	if err != nil {
		// The error can be user.ErrorNotFound, but we are not deleting
		// user at this moment, so this shouldn't happen.
		log.Errorf("Failed to fetch user %q from repo: %v: ", userID, err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	signer, err := s.KeyManager.Signer()
	if err != nil {
		log.Errorf("Failed to refresh ID token: %v", err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	now := time.Now()
	expireAt := now.Add(session.DefaultSessionValidityWindow)

	claims := oidc.NewClaims(s.IssuerURL.String(), user.ID, creds.ID, now, expireAt)
	user.AddToClaims(claims)

	jwt, err := jose.NewSignedJWT(claims, signer)
	if err != nil {
		log.Errorf("Failed to generate ID token: %v", err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	log.Infof("New token sent: clientID=%s", creds.ID)

	return jwt, nil
}
Exemple #9
0
// writeResponseWithBody attempts to marshal an arbitrary thing to JSON then write
// it to the http.ResponseWriter
func writeResponseWithBody(w http.ResponseWriter, code int, resp interface{}) {
	enc, err := json.Marshal(resp)
	if err != nil {
		log.Errorf("Failed JSON-encoding HTTP response: %v", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	if _, err = w.Write(enc); err != nil {
		log.Errorf("Failed writing HTTP response: %v", err)
	}
}
Exemple #10
0
func (u *UserEmailer) signedClaimsToken(claims jose.Claims) (string, error) {
	signer, err := u.signerFn()
	if err != nil || signer == nil {
		log.Errorf("error getting signer: %v (%v)", err, signer)
		return "", err
	}

	jwt, err := jose.NewSignedJWT(claims, signer)
	if err != nil {
		log.Errorf("error constructing or signing a JWT: %v", err)
		return "", err
	}
	return jwt.Encode(), nil
}
Exemple #11
0
func (c *clientResource) create(w http.ResponseWriter, r *http.Request) {
	ct := r.Header.Get("content-type")
	if ct != "application/json" {
		log.Debugf("Unsupported request content-type: %v", ct)
		writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, "unsupported content-type"))
		return
	}

	var sc schema.Client
	dec := json.NewDecoder(r.Body)
	err := dec.Decode(&sc)
	if err != nil {
		log.Debugf("Error decoding request body: %v", err)
		writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, "unable to decode request body"))
		return
	}

	ci, err := schema.MapSchemaClientToClientIdentity(sc)
	if err != nil {
		log.Debugf("Invalid request data: %v", err)
		writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, "missing or invalid field: redirectURIs"))
		return
	}

	if err := ci.Metadata.Valid(); err != nil {
		log.Debugf("ClientMetadata invalid: %v", err)
		writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, err.Error()))
		return
	}

	clientID, err := oidc.GenClientID(ci.Metadata.RedirectURIs[0].Host)
	if err != nil {
		log.Errorf("Failed generating ID for new client: %v", err)
		writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to generate client ID"))
		return
	}

	creds, err := c.repo.New(clientID, ci.Metadata)
	if err != nil {
		log.Errorf("Failed creating client: %v", err)
		writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to create client"))
		return
	}
	ci.Credentials = *creds

	ssc := schema.MapClientIdentityToSchemaClientWithSecret(ci)
	w.Header().Add("Location", phttp.NewResourceLocation(r.URL, ci.Credentials.ID))
	writeResponseWithBody(w, http.StatusCreated, ssc)
}
Exemple #12
0
func (h *SendResetPasswordEmailHandler) exchangeKeyForClientAndRedirect(key string) (string, url.URL, error) {
	id, err := h.sm.ExchangeKey(key)
	if err != nil {
		log.Errorf("error exchanging key: %v ", err)
		return "", url.URL{}, err
	}

	ses, err := h.sm.Kill(id)
	if err != nil {
		log.Errorf("error killing session: %v", err)
		return "", url.URL{}, err
	}

	return ses.ClientID, ses.RedirectURL, nil
}
Exemple #13
0
func (u *UserEmailer) userPasswordInfo(email string) (user.User, user.PasswordInfo, error) {
	usr, err := u.ur.GetByEmail(nil, email)
	if err != nil {
		log.Errorf("Error getting user: %q", err)
		return user.User{}, user.PasswordInfo{}, err
	}

	pwi, err := u.pwi.Get(nil, usr.ID)
	if err != nil {
		log.Errorf("Error getting password: %q", err)
		return user.User{}, user.PasswordInfo{}, err
	}

	return usr, pwi, nil
}
Exemple #14
0
func (c *OAuth2Connector) handleCallbackFunc(lf oidc.LoginFunc, errorURL url.URL) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		q := r.URL.Query()

		e := q.Get("error")
		if e != "" {
			redirectError(w, errorURL, q)
			return
		}

		code := q.Get("code")
		if code == "" {
			q.Set("error", oauth2.ErrorInvalidRequest)
			q.Set("error_description", "code query param must be set")
			redirectError(w, errorURL, q)
			return
		}
		sessionKey := q.Get("state")

		token, err := c.conn.Client().RequestToken(oauth2.GrantTypeAuthCode, code)
		if err != nil {
			log.Errorf("Unable to verify auth code with issuer: %v", err)
			q.Set("error", oauth2.ErrorUnsupportedResponseType)
			q.Set("error_description", "unable to verify auth code with issuer")
			redirectError(w, errorURL, q)
			return
		}
		ident, err := c.conn.Identity(newAuthenticatedClient(token, http.DefaultClient))
		if err != nil {
			log.Errorf("Unable to retrieve identity: %v", err)
			q.Set("error", oauth2.ErrorUnsupportedResponseType)
			q.Set("error_description", "unable to retrieve identity from issuer")
			redirectError(w, errorURL, q)
			return
		}
		redirectURL, err := lf(ident, sessionKey)
		if err != nil {
			log.Errorf("Unable to log in %#v: %v", ident, err)
			q.Set("error", oauth2.ErrorAccessDenied)
			q.Set("error_description", "login failed")
			redirectError(w, errorURL, q)
			return
		}
		w.Header().Set("Location", redirectURL)
		w.WriteHeader(http.StatusFound)
		return
	}
}
Exemple #15
0
func (h *SendResetPasswordEmailHandler) handleGET(w http.ResponseWriter, r *http.Request) {
	sessionKey := r.URL.Query().Get("session_key")
	if sessionKey != "" {
		clientID, redirectURL, err := h.exchangeKeyForClientAndRedirect(sessionKey)
		if err == nil {
			handleURL := *r.URL
			q := r.URL.Query()
			q.Del("session_key")
			q.Set("redirect_uri", redirectURL.String())
			q.Set("client_id", clientID)
			handleURL.RawQuery = q.Encode()
			http.Redirect(w, r, handleURL.String(), http.StatusSeeOther)
			return
		}
		// Even though we could not exchange the sessionKey to get a
		// redirect URL, we can still continue as if they didn't pass
		// one in, so we don't return here.
		log.Errorf("could not exchange sessionKey: %v", err)
	}
	data := sendResetPasswordEmailData{}
	if err := h.fillData(r, &data); err != nil {
		writeAPIError(w, http.StatusBadRequest, err)
	}

	if data.ClientID == "" {
		writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest,
			"missing required parameters"))
		return
	}

	execTemplate(w, h.tpl, data)
}
Exemple #16
0
func (r *userRepo) GetRemoteIdentities(tx repo.Transaction, userID string) ([]user.RemoteIdentity, error) {
	ex := r.executor(tx)
	if userID == "" {
		return nil, user.ErrorInvalidID
	}

	qt := r.quote(remoteIdentityMappingTableName)
	rims, err := ex.Select(&remoteIdentityMappingModel{}, fmt.Sprintf("SELECT * FROM %s WHERE user_id = $1", qt), userID)

	if err != nil {
		if err != sql.ErrNoRows {
			return nil, err
		}
		return nil, nil
	}
	if len(rims) == 0 {
		return nil, nil
	}

	var ris []user.RemoteIdentity
	for _, m := range rims {
		rim, ok := m.(*remoteIdentityMappingModel)
		if !ok {
			log.Errorf("expected remoteIdentityMappingModel but found %v", reflect.TypeOf(m))
			return nil, errors.New("unrecognized model")
		}

		ris = append(ris, user.RemoteIdentity{
			ID:          rim.RemoteID,
			ConnectorID: rim.ConnectorID,
		})
	}

	return ris, nil
}
Exemple #17
0
func (c *LDAPConnector) Groups(fullUserID string) ([]string, error) {
	if !c.searchBeforeAuth {
		return nil, fmt.Errorf("cannot search without service account")
	}
	if c.searchGroupFilter == "" {
		return nil, fmt.Errorf("no group filter specified")
	}

	var groups []string
	err := c.ldapPool.Do(func(conn *ldap.Conn) error {
		if err := conn.Bind(c.searchBindDN, c.searchBindPw); err != nil {
			if !invalidBindCredentials(err) {
				log.Errorf("failed to connect to LDAP for search bind: %v", err)
			}
			return fmt.Errorf("failed to bind: %v", err)
		}

		req := &ldap.SearchRequest{
			BaseDN: c.baseDN,
			Scope:  c.searchScope,
			Filter: c.formatDN(c.searchGroupFilter, fullUserID),
		}
		resp, err := conn.Search(req)
		if err != nil {
			return fmt.Errorf("search failed: %v", err)
		}
		groups = make([]string, len(resp.Entries))
		for i, entry := range resp.Entries {
			groups[i] = entry.DN
		}
		return nil
	})
	return groups, err
}
Exemple #18
0
func (r *clientIdentityRepo) SetDexAdmin(clientID string, isAdmin bool) error {
	tx, err := r.begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()
	exec := r.executor(tx)

	m, err := exec.Get(clientIdentityModel{}, clientID)
	if m == nil || err != nil {
		return err
	}

	cim, ok := m.(*clientIdentityModel)
	if !ok {
		log.Errorf("expected clientIdentityModel but found %v", reflect.TypeOf(m))
		return errors.New("unrecognized model")
	}

	cim.DexAdmin = isAdmin
	_, err = exec.Update(cim)
	if err != nil {
		return err
	}

	return tx.Commit()
}
Exemple #19
0
func (r *clientIdentityRepo) SetDexAdmin(clientID string, isAdmin bool) error {
	tx, err := r.dbMap.Begin()
	if err != nil {
		return err
	}

	m, err := r.dbMap.Get(clientIdentityModel{}, clientID)
	if m == nil || err != nil {
		rollback(tx)
		return err
	}

	cim, ok := m.(*clientIdentityModel)
	if !ok {
		rollback(tx)
		log.Errorf("expected clientIdentityModel but found %v", reflect.TypeOf(m))
		return errors.New("unrecognized model")
	}

	cim.DexAdmin = isAdmin
	_, err = r.dbMap.Update(cim)
	if err != nil {
		rollback(tx)
		return err
	}

	err = tx.Commit()
	if err != nil {
		rollback(tx)
		return err
	}

	return nil
}
Exemple #20
0
func handleOOBFunc(s *Server, tpl *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			w.Header().Set("Allow", "GET")
			phttp.WriteError(w, http.StatusMethodNotAllowed, "GET only acceptable method")
			return
		}

		key := r.URL.Query().Get("code")
		if key == "" {
			phttp.WriteError(w, http.StatusBadRequest, "Invalid Session")
			return
		}
		sessionID, err := s.SessionManager.ExchangeKey(key)
		if err != nil {
			phttp.WriteError(w, http.StatusBadRequest, "Invalid Session")
			return
		}
		code, err := s.SessionManager.NewSessionKey(sessionID)
		if err != nil {
			log.Errorf("problem getting NewSessionKey: %v", err)
			phttp.WriteError(w, http.StatusInternalServerError, "Internal Server Error")
			return
		}

		execTemplate(w, tpl, map[string]string{
			"code": code,
		})
	}
}
Exemple #21
0
func (r *SessionKeyRepo) Pop(key string) (string, error) {
	m, err := r.dbMap.Get(sessionKeyModel{}, key)
	if err != nil {
		return "", err
	}

	skm, ok := m.(*sessionKeyModel)
	if !ok {
		return "", errors.New("unrecognized model")
	}

	if skm.Stale || skm.ExpiresAt < r.clock.Now().Unix() {
		return "", errors.New("invalid session key")
	}

	qt := pq.QuoteIdentifier(sessionKeyTableName)
	q := fmt.Sprintf("UPDATE %s SET stale=$1 WHERE key=$2 AND stale=$3", qt)
	res, err := r.dbMap.Exec(q, true, key, false)
	if err != nil {
		return "", err
	}

	if n, err := res.RowsAffected(); n != 1 {
		if err != nil {
			log.Errorf("Failed determining rows affected by UPDATE session_key query: %v", err)
		}
		return "", fmt.Errorf("failed to pop entity")
	}

	return skm.SessionID, nil
}
Exemple #22
0
// addClaimsFromScope adds claims that are based on the scopes that the client requested.
// Currently, these include cross-client claims (aud, azp).
func (s *Server) addClaimsFromScope(claims jose.Claims, scopes scope.Scopes, clientID string) error {
	crossClientIDs := scopes.CrossClientIDs()
	if len(crossClientIDs) > 0 {
		var aud []string
		for _, id := range crossClientIDs {
			if clientID == id {
				aud = append(aud, id)
				continue
			}
			allowed, err := s.CrossClientAuthAllowed(clientID, id)
			if err != nil {
				log.Errorf("Failed to check cross client auth. reqClientID %v; authClient:ID %v; err: %v", clientID, id, err)
				return oauth2.NewError(oauth2.ErrorServerError)
			}
			if !allowed {
				err := oauth2.NewError(oauth2.ErrorInvalidRequest)
				err.Description = fmt.Sprintf(
					"%q is not authorized to perform cross-client requests for %q",
					clientID, id)
				return err
			}
			aud = append(aud, id)
		}
		if len(aud) == 1 {
			claims.Add("aud", aud[0])
		} else {
			claims.Add("aud", aud)
		}
		claims.Add("azp", clientID)
	}
	return nil
}
Exemple #23
0
func handleResendFunc(o *OtsimoAccounts, issuerURL, resendURL, cbURL url.URL) http.HandlerFunc {
	trans := &oidc.AuthenticatedTransport{
		TokenRefresher: &ClientCredsTokenRefresher{
			Issuer:     issuerURL.String(),
			OIDCClient: o.Oidc,
		},
		RoundTripper: http.DefaultTransport,
	}
	hc := &http.Client{Transport: trans}

	return func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		tok := r.Form.Get("jwt")
		q := struct {
			Token       string `json:"token"`
			RedirectURI string `json:"redirectURI"`
		}{
			Token:       tok,
			RedirectURI: cbURL.String(),
		}
		qBytes, err := json.Marshal(&q)
		res, err := hc.Post(resendURL.String(), "application/json", bytes.NewReader(qBytes))
		if err != nil {
			log.Errorf("error requesting email resend: %v", err)
			writeError(w, http.StatusInternalServerError, "error requesting email resend")
			return
		}

		w.Write([]byte(fmt.Sprintf("Status from Dex: %v", res.Status)))
	}
}
Exemple #24
0
func (gc *GarbageCollector) Run() chan struct{} {
	stop := make(chan struct{})

	go func() {
		var failing bool
		next := gc.interval
		for {
			select {
			case <-gc.clock.After(next):
				if anyPurgeErrors(purgeAll(gc.purgers)) {
					if !failing {
						failing = true
						next = time.Second
					} else {
						next = ptime.ExpBackoff(next, time.Minute)
					}
					log.Errorf("Failed garbage collection, retrying in %v", next)
				} else {
					failing = false
					next = gc.interval
					log.Infof("Garbage collection complete, running again in %v", next)
				}
			case <-stop:
				return
			}
		}
	}()

	return stop
}
Exemple #25
0
func (r *SessionRepo) Get(sessionID string) (*session.Session, error) {
	m, err := r.dbMap.Get(sessionModel{}, sessionID)
	if err != nil {
		return nil, err
	}

	if m == nil {
		return nil, errors.New("session does not exist")
	}

	sm, ok := m.(*sessionModel)
	if !ok {
		log.Errorf("expected sessionModel but found %v", reflect.TypeOf(m))
		return nil, errors.New("unrecognized model")
	}

	ses, err := sm.session()
	if err != nil {
		return nil, err
	}
	if ses.ExpiresAt.Before(r.clock.Now()) {
		return nil, errors.New("session does not exist")
	}

	return ses, nil
}
Exemple #26
0
func anyPurgeErrors(errchan <-chan purgeError) (found bool) {
	for perr := range errchan {
		found = true
		log.Errorf("Failed purging %s: %v", perr.name, perr.err)
	}
	return
}
Exemple #27
0
// SendResetPasswordEmail sends a password reset email to the user specified by the email addresss, containing a link with a signed token which can be visitied to initiate the password change/reset process.
// This method DOES NOT check for client ID, redirect URL validity - it is expected that upstream users have already done so.
// A link that can be used to reset the given user's password is returned.
func (u *UserEmailer) SendResetPasswordEmail(email string, redirectURL url.URL, clientID string) (*url.URL, error) {
	usr, pwi, err := u.userPasswordInfo(email)
	if err != nil {
		return nil, err
	}

	passwordReset := user.NewPasswordReset(usr.ID, pwi.Password, u.issuerURL,
		clientID, redirectURL, u.tokenValidityWindow)

	token, err := u.signedClaimsToken(passwordReset.Claims)
	if err != nil {
		return nil, err
	}

	resetURL := u.passwordResetURL
	q := resetURL.Query()
	q.Set("token", token)
	resetURL.RawQuery = q.Encode()

	if u.emailer != nil {
		err = u.emailer.SendMail(u.fromAddress, "Reset Your Password", "password-reset",
			map[string]interface{}{
				"email": usr.Email,
				"link":  resetURL.String(),
			}, usr.Email)
		if err != nil {
			log.Errorf("error sending password reset email %v: ", err)
		}
		return nil, err
	}
	return &resetURL, nil
}
Exemple #28
0
// SendInviteEmail is sends an email that allows the user to both
// reset their password *and* verify their email address. Similar to
// SendResetPasswordEmail, the given url and client id are assumed
// valid. A link that can be used to validate the given email address
// and reset the password is returned.
func (u *UserEmailer) SendInviteEmail(email string, redirectURL url.URL, clientID string) (*url.URL, error) {
	usr, pwi, err := u.userPasswordInfo(email)
	if err != nil {
		return nil, err
	}

	invitation := user.NewInvitation(usr, pwi.Password, u.issuerURL,
		clientID, redirectURL, u.tokenValidityWindow)

	token, err := u.signedClaimsToken(invitation.Claims)
	if err != nil {
		return nil, err
	}

	resetURL := u.invitationURL
	q := resetURL.Query()
	q.Set("token", token)
	resetURL.RawQuery = q.Encode()

	if u.emailer != nil {
		err = u.emailer.SendMail("Activate Your Account", "invite",
			map[string]interface{}{
				"email": usr.Email,
				"link":  resetURL.String(),
			}, usr.Email)
		if err != nil {
			log.Errorf("error sending password reset email %v: ", err)
		}
		return nil, err
	}
	return &resetURL, nil
}
Exemple #29
0
func handleRegisterFunc(o *OtsimoAccounts) http.HandlerFunc {
	handlePOST := func(w http.ResponseWriter, r *http.Request) {
		r.ParseForm()
		email := r.PostFormValue("username")
		password := r.PostFormValue("password")
		firstName := r.PostFormValue("first_name")
		lastName := r.PostFormValue("last_name")
		language := r.PostFormValue("language")
		if email == "" || password == "" {
			writeError(w, http.StatusBadRequest, "invalid body")
			return
		}
		result, err := registerUser(o, email, password, firstName, lastName, language)
		if err != nil {
			writeError(w, http.StatusInternalServerError, err.Error())
			return
		}
		writeResponseWithBody(w, http.StatusOK, result.Token)
	}
	handleGET := func(w http.ResponseWriter, r *http.Request) {
		oac, err := o.Oidc.OAuthClient()
		if err != nil {
			log.Errorf("failed to create OAuthClient %v", err)
			writeError(w, http.StatusInternalServerError, err.Error())
		}

		u, err := url.Parse(oac.AuthCodeURL("", "", ""))
		q := u.Query()
		q.Set("register", "1")
		if err != nil {
			log.Errorf("failed to create authCoreURL %v", err)
			writeError(w, http.StatusInternalServerError, err.Error())
		}
		u.RawQuery = q.Encode()
		log.Infof("URL: %v", u.String())
		http.Redirect(w, r, u.String(), http.StatusFound)
	}
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "POST" {
			handlePOST(w, r)
		} else if r.Method == "GET" {
			handleGET(w, r)
		} else {
			writeError(w, http.StatusNotFound, "wrong Http Verb")
		}
	}
}
Exemple #30
0
func (s *grpcServer) authToken(jwt jose.JWT) (string, *oidc.ClientMetadata, error) {
	ciRepo := s.server.ClientIdentityRepo
	keys, err := s.server.KeyManager.PublicKeys()
	if err != nil {
		log.Errorf("grpc.go: Failed to get keys: %v", err)
		return "", nil, errors.New("errorAccessDenied")
	}
	if len(keys) == 0 {
		log.Error("grpc.go: No keys available for verification client")
		return "", nil, errors.New("errorAccessDenied")
	}

	ok, err := oidc.VerifySignature(jwt, keys)
	if err != nil {
		log.Errorf("grpc.go: Failed to verify signature: %v", err)
		return "", nil, err
	}
	if !ok {
		log.Info("grpc.go: token signature is not verified")
		return "", nil, errors.New("invalid token")
	}

	clientID, err := oidc.VerifyClientClaims(jwt, s.server.IssuerURL.String())
	if err != nil {
		log.Errorf("grpc.go: Failed to verify JWT claims: %v", err)
		return "", nil, errors.New("failed to verify jwt claims token")
	}

	md, err := ciRepo.Metadata(clientID)
	if md == nil || err != nil {
		log.Errorf("grpc.go: Failed to find clientID: %s, error=%v", clientID, err)
		return "", nil, err
	}
	//client must be admin in order to use login and register grpc apis.
	ok, err = ciRepo.IsDexAdmin(clientID)
	if err != nil {
		return "", nil, err
	}

	if !ok {
		log.Infof("grpc.go: Client [%s] is not admin", clientID)
		return "", nil, errors.New("errorAccessDenied")
	}

	log.Debugf("grpc.go: Authenticated token for client ID %s", clientID)
	return clientID, md, nil
}