예제 #1
0
파일: env.go 프로젝트: lmineiro/hydra
func getEnv() {
	listenOn = fmt.Sprintf(
		"%s:%s",
		env.Getenv("HOST", ""),
		env.Getenv("PORT", "4443"),
	)
	accessTokenLifetime = env.Getenv("OAUTH2_ACCESS_TOKEN_LIFETIME", "3600")
	forceHTTP = env.Getenv("DANGEROUSLY_FORCE_HTTP", "")
	hostURL = env.Getenv("HOST_URL", "https://localhost:4443")
	providers = []provider.Provider{
		dropbox.New(
			"dropbox",
			env.Getenv("DROPBOX_CLIENT", ""),
			env.Getenv("DROPBOX_SECRET", ""),
			pkg.JoinURL(hostURL, "/oauth2/auth"),
		),
		signin.New(
			"login",
			env.Getenv("SIGNIN_URL", ""),
			pkg.JoinURL(hostURL, "/oauth2/auth"),
		),
	}
	bcryptWorkFactor = env.Getenv("BCRYPT_WORKFACTOR", "10")
	databaseURL = env.Getenv("DATABASE_URL", "")
	locations = map[string]string{
		"signUp": env.Getenv("SIGNUP_URL", ""),
		"signIn": env.Getenv("SIGNIN_URL", ""),
	}
	jwtPrivateKeyPath = env.Getenv("JWT_PRIVATE_KEY_PATH", path.Join(os.Getenv("GOPATH"), "src", "github.com", "ory-am", "hydra", "example", "cert", "rs256-private.pem"))
	jwtPublicKeyPath = env.Getenv("JWT_PUBLIC_KEY_PATH", path.Join(os.Getenv("GOPATH"), "src", "github.com", "ory-am", "hydra", "example", "cert", "rs256-public.pem"))
	tlsKeyPath = env.Getenv("TLS_KEY_PATH", path.Join(os.Getenv("GOPATH"), "src", "github.com", "ory-am", "hydra", "example", "cert", "tls-key.pem"))
	tlsCertPath = env.Getenv("TLS_CERT_PATH", path.Join(os.Getenv("GOPATH"), "src", "github.com", "ory-am", "hydra", "example", "cert", "tls-cert.pem"))
}
예제 #2
0
파일: client.go 프로젝트: emmanuel/hydra
func isValidAuthorizeRequest(c *HTTPClient, ar *AuthorizeRequest, retry bool) (bool, error) {
	request := gorequest.New()
	resp, body, errs := request.Post(pkg.JoinURL(c.ep, "/guard/allowed")).SetBasicAuth(c.clientConfig.ClientID, c.clientConfig.ClientSecret).Set("Content-Type", "application/json").Send(*ar).End()
	if len(errs) > 0 {
		return false, errors.Errorf("Got errors: %v", errs)
	} else if retry && resp.StatusCode == http.StatusUnauthorized {
		var err error
		if c.clientToken, err = c.clientConfig.Token(oauth2.NoContext); err != nil {
			return false, errors.New(err)
		} else if c.clientToken == nil {
			return false, errors.New("Access token could not be retrieved")
		}
		return isValidAuthorizeRequest(c, ar, false)
	} else if resp.StatusCode != http.StatusOK {
		return false, errors.Errorf("Status code %d is not 200: %s", resp.StatusCode, body)
	}

	if err := json.Unmarshal([]byte(body), &isAllowed); err != nil {
		return false, errors.Errorf("Could not unmarshall body because %s", err.Error())
	}

	if !isAllowed.Allowed {
		return false, errors.New("Authroization denied")
	}
	return isAllowed.Allowed, nil
}
예제 #3
0
파일: client.go 프로젝트: emmanuel/hydra
func isValidAuthenticationRequest(c *HTTPClient, token string, retry bool) (bool, error) {
	data := url.Values{}
	data.Set("token", token)
	request := gorequest.New()
	resp, body, errs := request.Post(pkg.JoinURL(c.ep, "/oauth2/introspect")).Type("form").SetBasicAuth(c.clientConfig.ClientID, c.clientConfig.ClientSecret).SendString(data.Encode()).End()
	if len(errs) > 0 {
		return false, errors.Errorf("Got errors: %v", errs)
	} else if resp.StatusCode != http.StatusOK {
		return false, errors.Errorf("Status code %d is not 200: %s", resp.StatusCode, body)
	}

	if retry && resp.StatusCode == http.StatusUnauthorized {
		var err error
		if c.clientToken, err = c.clientConfig.Token(oauth2.NoContext); err != nil {
			return false, errors.New(err)
		} else if c.clientToken == nil {
			return false, errors.New("Access token could not be retrieved")
		}
		return isValidAuthenticationRequest(c, token, false)
	} else if resp.StatusCode != http.StatusOK {
		return false, fmt.Errorf("Status code %d is not 200", resp.StatusCode)
	}

	var introspect struct {
		Active bool `json:"active"`
	}

	if err := json.Unmarshal([]byte(body), &introspect); err != nil {
		return false, err
	} else if !introspect.Active {
		return false, errors.New("Authentication denied")
	}
	return introspect.Active, nil
}
예제 #4
0
파일: client.go 프로젝트: emmanuel/hydra
func New(endpoint, client, secret string) *HTTPClient {
	return &HTTPClient{
		ep: endpoint,
		clientConfig: &clientcredentials.Config{
			ClientSecret: secret,
			ClientID:     client,
			TokenURL:     pkg.JoinURL(endpoint, "oauth2/token"),
		},
		clientToken: &oauth2.Token{},
	}
}
예제 #5
0
func JoinURLStrings(host string, args ...string) string {
	return pkg.JoinURL(host, args...)
}
예제 #6
0
func (h *Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	resp := h.server.NewResponse()
	defer resp.Close()

	code := r.Form.Get("code")
	state := r.Form.Get("state")
	if code != "" {
		stateData, err := h.States.GetStateData(state)
		if err != nil {
			// Something else went wrong
			http.Error(w, fmt.Sprintf("Could not fetch state: %s", err), http.StatusBadRequest)
			return
		}
		if stateData.IsExpired() {
			http.Error(w, fmt.Sprintf("This session expired %v.", err), http.StatusBadRequest)
		}
		r.Form = stateData.ToURLValues()
	}

	if ar := h.server.HandleAuthorizeRequest(resp, r); ar != nil {
		// For now, a provider must be given.
		// TODO there should be a fallback provider which is a redirect to the login endpoint. This should be configurable by env var.
		// Let's see if this is a valid provider. If not, return an error.
		providerName := r.Form.Get("provider")
		if r.Form.Get("provider") == "" && h.SignInLocation != "" {
			providerName = "login"
		}

		provider, err := h.Providers.Find(providerName)
		if err != nil {
			http.Error(w, fmt.Sprintf(`Unknown provider "%s".`, providerName), http.StatusBadRequest)
			return
		}

		if code == "" {
			stateData := new(storage.StateData)
			if err := stateData.FromAuthorizeRequest(ar, provider.GetID()); err != nil {
				// Something else went wrong
				http.Error(w, fmt.Sprintf("Could not hydrate state data: %s", err), http.StatusInternalServerError)
				return
			}
			stateData.ExpireInOneHour()
			if err := h.States.SaveStateData(stateData); err != nil {
				// Something else went wrong
				http.Error(w, fmt.Sprintf("Could not persist state data: %s", err), http.StatusInternalServerError)
				return
			}

			// If no code was given we have to initiate the provider's authorization workflow
			url := provider.GetAuthenticationURL(stateData.ID)
			http.Redirect(w, r, url, http.StatusFound)
			return
		}

		// Create a session by exchanging the code for the auth code
		session, err := provider.FetchSession(code)
		if err != nil {
			http.Error(w, fmt.Sprintf("Could not exchange access code: %s", err), http.StatusUnauthorized)
			return
		}

		var conn connection.Connection
		var acc account.Account
		if session.GetForcedLocalSubject() != "" {
			acc, err = h.Accounts.Get(session.GetForcedLocalSubject())
		} else {
			conn, err = h.Connections.FindByRemoteSubject(provider.GetID(), session.GetRemoteSubject())
		}

		if err == pkg.ErrNotFound {
			// The subject is not linked to any account.

			if h.SignUpLocation == "" {
				http.Error(w, "No sign up location is set. Please contact your admin.", http.StatusInternalServerError)
				return
			}

			redirect, err := url.Parse(h.SignUpLocation)
			if err != nil {
				http.Error(w, fmt.Sprintf("Could not parse redirect URL: %s", err), http.StatusInternalServerError)
				return
			}

			claims := map[string]interface{}{
				"iss":                h.Issuer,
				"aud":                redirect.String(),
				"exp":                time.Now().Add(time.Hour),
				"iat":                time.Now(),
				"state":              ar.State,
				"connector_id":       provider.GetID(),
				"connector_response": session.GetExtra(),
				"connector_subject":  session.GetRemoteSubject(),
				"redirect_uri":       pkg.JoinURL(h.HostURL, "oauth2/authorize"),
			}
			authToken, err := h.JWT.SignToken(claims, map[string]interface{}{})
			if err != nil {
				http.Error(w, fmt.Sprintf("Could not generate token: %s", err), http.StatusInternalServerError)
				return
			}

			query := redirect.Query()
			query.Add("auth_token", authToken)
			redirect.RawQuery = query.Encode()

			log.WithFields(log.Fields{
				"provider": provider.GetID(),
				"subject":  session.GetRemoteSubject(),
				"redirect": h.SignUpLocation,
			}).Warnf(`Remote subject is not linked to any local subject. Redirecting to sign up page.`)
			http.Redirect(w, r, redirect.String(), http.StatusFound)
			return
		} else if err != nil {
			// Something else went wrong
			http.Error(w, fmt.Sprintf("Could not assert subject claim: %s", err), http.StatusInternalServerError)
			return
		}

		var localSubject string
		if conn != nil {
			localSubject = conn.GetLocalSubject()
		} else if acc != nil {
			localSubject = acc.GetID()
		}

		ar.UserData = jwt.NewClaimsCarrier(uuid.New(), h.Issuer, localSubject, ar.Client.GetId(), time.Now().Add(time.Duration(ar.Expiration)*time.Second), time.Now(), time.Now())
		ar.Authorized = true
		h.server.FinishAuthorizeRequest(resp, r, ar)
	}

	if resp.IsError {
		resp.StatusCode = http.StatusUnauthorized
	}

	osin.OutputJSON(resp, w, r)
}